공유객체
volatile
- 선언된 변수를 컴파일러의 최적화 대상에서 제외시킴.
=> 값이 변경되는 즉시 변수에 적용
- 다중 스레드에서 하나의 변수가 완벽하게 한번에 작동되도록 보장하는 키워드
=> 일종의 동기화
동기화
- 과도한 동기화는 프로그램 성능을 저하시킴.
- 필요한 영역에 선별적으로 사용.
동기화 메서드
- 메서드 자체에 동기화 처리 하기 : synchronized
- 여러 개의 Thread 들이 공유객체의 synchronized 메서드를 사용할 때 먼저 호출한 객체가 사용권 획득
- synchronized 아닌 메서드는 다른 스레드들이 synchronized 메서드 실행하면서 사용권을 획득했다 하더라도 상관없이 실행됨
- 메서드 코드가 길어지면 마지막에 대기하는 스레드가 너무 오래 기다리는 것을 막기 위해서 동기화블럭 사용
동기화 블럭
- 메서드 내 문제 발생 여지가 있을만한 임계영역에 동기화 처리
- synchronized(this){...}
- 필요한 영역(ex.동시에 작업하면 안되는 영역)만 동기화처리 가능
- 특정 스레드 객체가 이 영역 실행하는 중에 다른 스레드는 Blocked
lock 객체
- Lock 클래스 이용
- Lock 객체 생성 : 되도록이면 private final(다른 객체에서 접근 못하게)
- lock() : 동기화 시작
- unlock() : 동기화 해제 (반드시 해제 해야함)
- synchronized 단점 : 동기화 최대범위가 메서드
- lock()은 광범위하게 사용가능하지만 반드시 해제 필요!
- try~catch 블럭 사용할 경우에는 finally 블럭에서 unlock()
예외발생에 관계없이 lock() 해제해야하기 때문
private final ReentrantLock lock = new ReentrantLock();
lock.lock();
...
lock.unlock();
Collections 동기화
- Vector, Hashtable 등 예전부터 존재하던 Collection 클래스는 내부에 동기화처리 되어있음
- 최근 새로 구성된 Collection 들은 동기화처리 되어있지 않음
- 동기화 필요한 프로그램에서 이런 Collection 사용하려면 동기화처리 후 사용해야함
- Collections의 정적메서드 중 synchronized로 시작하는 메서드 이용
(Collections 클래스가 제공하는 동기화메서드 )
private static List<Integer> list =
Collections.synchronizedList(new ArrayList<>());