Concurrency in JDK 5.0 서울시립대학교 인공지능연구실 신현주 2007.05.05
What’s new in JDK 5.0 for concurrency JVM-level change Compare-and-swap (CAS) 지원 JDK library classes에서 사용하기 위한 변화 Low-level utility classes Locking ex) ReentrantLock Atomic variables ex) AtomicBoolean, Atomicinteger … High-level utility classes thread pool, barriers, semaphores, mutexes, exchangers …
Thread-safe collections Weakly consistent iterators Collection iterator 작업을 할 동안, collection을 수정할 경우 ConcurrentModificationException을 발생 CopyOnWriteArrayList / CopyOnWriteArraySet Collection에 추가/수정된 element을 backing array에 저장해서 문제를 해결. Iterator 작업 중에도 collection 수정 가능 ConcurrentHashMap 여러 개의 lock을 이용해서 문제를 해결
Thread-safe collections Queue List를 대부분 Queue 용도로 사용 기존 List collections은 새로 추가된 Queue interface를 구현하고 있음 BlockingQueue 보통 Queue를 사용하는 목적은 data 공유를 위해서이다. 생산자 Thread에서 data를 생산해 내는 속도와 소비자 Thread에서 data를 소비하는 속도가 다른 경우이다. Data 공유 목적으로 Queue를 사용하는 경우에 구현 방법 Polling 방식 - while(true) {} Blocking 방식 - Object.wait() / Object.notifyAll() BlockingQueue : Blocking 방식으로 Queue를 구현해 놓음 일반 메소드 (offer() / take())를 사용하는 것처럼 사용
Task management Thread creation Thread 생성은 컴퓨터 자원을 많이 소모하는 heavy job이다. 웹 서버와 같이 실제 작업 수행 시간은 짧지만, 많은 요청이 있는 경우, 매 요청마다 Thread를 생성하는 것은 overhead가 크다. 이 경우 모든 요청을 처리할 수 없을 수도 있다. 심각한 경우, 웹 서버가 멈춰버릴 수도 있다. Thread pool을 이용해서 Thread를 재사용한다.
Thread-safe collections The Executor framework Thread pool Executors.newFixedThreadPool(int n) 고정된 숫자의 Thread를 활용해서 Thread pool을 구현 Executors.newCachedThreadPool() Thread의 제한은 없다. 사용 가능한 Thread가 부족하면 새 Thread를 생성한다. Task가 끝나면 일정 시간 Thread를 가지고 있다가 더 이상 사용하지 않으면 Thread를 폐기한다. Executors.newSingleThreadPool() 한 개의 Thread를 사용해서 Thread pool을 구현. 많은 수의, 수행 시간이 짧은 Background 작업을 하는데 적합
Thread-safe collections The Future interface Task의 완료되었는지 확인할 수 있다. Task 수행을 중간에 cancel할 수 있다. Task 수행 결과를 확인할 수 있다. CompletionService Task 수행과 Task 결과를 사용한 processing을 분리한다.
Synchronizer classes Semaphores Mutex CyclicBarrier Counting semaphores 지정된 수의 thread만 blocking 구역 안에 들어갈 수 있다. Mutex Counting semaphores의 특별한 형태 1개의 Thread만 blocking 구역 안에 들어갈 수 있다. CyclicBarrier 지정된 수의 Thread 모두가 barrier point에 도착할 때까지 대기 상태로 만들기 위한 방법을 제공한다. 또한 지정된 수의 Thread 모두가 barrier point에 도착하면, 추가적인 작업을 할 수 있는 방법을 제공한다.
Synchronizer classes CountdownLatch Exchanger CyclicBarrier와 비슷한 역할을 한다. barrier point 도착과 대기 상태를 분리시켰다. CyclicBarrier.await()를 부르면 해당 Thread는 barrier point에 도착한 것이 되고 바로 대기 상태에 들어가게 된다. CountdownLatch에서는 barrier point 도착은 CountdownLatch.countDown()으로 대기 상태는 CountdownLatch.await()로 분리시켰다. Exchanger 두 Thread 간의 data 객체 교환을 위한 방법을 제공한다. 소비자, 생산자 문제에서 소비자, 생산자 각각 버퍼를 가지고 있는 경우 소비자는 버퍼가 가득 찼을 때 Exchanger의 barrier point를 부르고, 생산자는 버퍼는 텅 비게 되었을 때 Exchanger의 barrier point를 부른다. 두 Thread 모두 barrier point에 도착하면, 생산자와 소비자의 버퍼를 서로 교환하게 된다.
Low-level facilities Lock Atomic variables synchronized 성능 계선 Compare-and-swap (CAS)를 활용 java.util.concurrent 패키지 구현에 사용한 기본 객체