
쓰레드 상태와 제어 (2)
join()
-정해진 시간동안 지정한 쓰레드가 작업하는 것을 기다린다
-시간을 지정하지 않았을 때는 지정한 쓰레드의 작업이 끝날 때까지 기다린다.
-interrupt() 를 만나면 기다리는 것을 멈추기 때문에 InterruptedException이 발생한다.
yield()
-남은 시간을 다음 쓰레드에게 양보하고 쓰레드 자신은 실행대기 상태가 됨
-thread1과 thread2가 같이 1초에 한번씩 출력되다가
-5초뒤에 thread1에서 InterruptedException이
-발상하면서 Thread.yield(); 이 실행되어 thread1은
-실행대기 상태로 변경되면서 남은 시간은 thread2에게 양보됩니다.
synchronized
-쓰레드가 진행중인 작업을 다른 쓰레드가 침범하지 못하도록 막는 것을 '쓰레드 동기화(Synchronization)
-동기화를 하려면 다른 쓰레드의 침범을 막아야하는 코드들을 ‘임계영역’으로 설정
-임계영역에는 Lock을 가진 단 하나의 쓰레드만 출입이 가능 (임계영역은 한번에 한 쓰레드만 사용이 가능)
-실행할 메서드 또는 실행할 코드 묶음 앞에 synchronized 를 붙여서 임계영역을 지정
wait()
-침범을 막은 코드를 수행하다가 작업을 더 이상 진행할 상황이 아니면, wait() 을 호출하여 쓰레드가 Lock을 반납하고 기다리게 할 수 있다
-실행 중이던 쓰레드는 해당 객체의 대기실(waiting pool)에서 통지를 기다린다.
notify()
-추후에 작업을 진행할 수 있는 상황이 되면 notify() 를 호출
-해당 객체의 대기실(waiting pool)에 있는 모든 쓰레드 중에서 임의의 쓰레드만 통지
Lock
-synchronized 블럭으로 동기화하면 자동적으로 Lock이 걸리고 풀리지만, 같은 메서드 내에서만 Lock을 걸 수 있다는 제약 -> 이 제약을 해결하기 위해 Lock 클래스를 사용한다.
1.ReentrantLock
-재진입 가능한 Lock,가장 일반적인 배타 Lock
-특정 조건에서 Lock을 풀고, 나중에 다시 Lock을 얻어 임계영역으로 진입이 가능
2.ReentrantReadWriteLock
-읽기를 위한 Lock과 쓰기를 위한 Lock을 따로 제공
-읽기에는 공유적이고, 쓰기에는 베타적인 Lock
-읽기 Lock이 걸려있으면 다른 쓰레드들도 읽기 Lock을 중복으로 걸고 읽기를 수행할 수 있습니다. (read-only)
-읽기 Lock이 걸려있는 상태에서 쓰기 Lock을 거는 것은 허용되지 않습니다. (데이터 변경 방지)
3.StampedLock
-ReentrantReadWriteLock에 낙관적인 Lock의 기능을 추가
-낙관적인 Lock : 데이터를 변경하기 전에 락을 걸지 않는 것을 말합니다.
낙관적인 락은 데이터 변경을 할 때 충돌이 일어날 가능성이 적은 상황에서 사용합니다.
-> 작업은 빠르지만 여러 쓰레드가 동시에 변경을 하려고 할때 적합하지 않다.
Condition
-스레드를 분리하여 특정 조건이 만족될 때만 깨운다
-ReentrantLock 클래스와 함께 사용
-await() & signal() 을 사용
📝오늘의 회고
오늘도! 쳐지지 말고 포기하지말고 힘내서 가보자고~~~