'10.03.24 story JAVA이야기2010. 4. 1. 15:02
유스케이스에 클래스가 있다.
<effective Java>
동시성
공유하는 가변 데이터에 접근 시 동기화하자
synchronized 키워드를 사용하면, 어느 한 시점에 하나의 스레드만이 메소드나 블록을 실행하게 할 수 있다.
동기화를 올바르게 사용하면 불안정한 상태의 객체를 어떤 메소드에서도 접근할 수 없도록 보장한다.
이 관점은 맞지만 아직은 할 얘기가 많다. 동기화를 하지 않으면, 하나의 스레드에서 변경한 내용을 다른 스레드에서 못 볼 수 있다. 동기화는 불안정 상태의 객체를 스레드가 볼 수 없도록 하는 것은 물론, 동기화된 메소드나 블록에 진입하는 각 스레드가 앞에서의 모든 변경이 반영된 결과를 볼 수 있게 해준다.
자바 언어 명세에서는 long이나 double 타입이 아닌 변수의 값을 읽거나 쓸 때는 원자성을 보장한다. long이나 double타입이 아닌 변수의 값을 읽으면 어떤 스레드가 그 변수에 저장했던 값을 반환 받을 수 있다는 것이다.
동기화는 상호 배타는 물론, 스레드 간의 신뢰성 있는 변수 값 전달에도 필요하다. 이것은자바 언어 명세의 메모리 모델에서 비롯된 것으로써, 메모리 모델에서는 한 스레드가 변경한 것을 언제 어떻게 다른 스레드가 볼 수 있는지 명시하고 있다.
Thread.stop을 사용하지 말자. 한 스레드에서 다른 스레드를 중단시킬 때 권장할만한 방법은 이렇다. 즉, 초기 값이 false인 boolean필드를 두 스레드가 공유하면서, ThreadB는 그 필드의 값을 계속 살피다가 true가 되면 스스로 중단하면 되고, ThreadA에서는 ThreadB를 중단하고자 할 때 그 필드의 값을 true로 바꾸면 된다.
while(!done)
I++;
if(!done)
while(true)
I++;
이런 최적화를 호이스팅이라고 하며, HotSpot서버 VM에서 바로 그렇게 한다. 이 결과는 활동 실패(스레드가 다음 작업을 못하고 영원히 대기하는 상태)로써, 프로그램이 진도를 못 나가서 실패한 것이다. 이 문제를 해결하는 한 가지 방법은 , stopRequested필드의 접근을 동기화하는 것이다.
필드 값을 변경하는 메소드와 읽는 메소드 모두 동기화되어 있다는 것에 유의하자. 값을 변경하는 메소드만 동기화하면 안 된다. 읽는 오퍼레이션과 변경하는 오퍼레이션 모두 동기화되어야만 동기화 효과가 생긴다.
위의 코드에서 루프의 매 반복당동기화 비용은 적은 편이지만, 코드의 양이 더 적고 성능이 더 좋은 또 다른 방법이 있다. 다음과 같이 stopRequested를 volatile로 선언하면 동기화를 생략할 수 있다. volatile은 상호 베타를 수행하지는 않지만 그 필드의 값을 읽는 스레드에서는 가장 최근에 변경된 값을 볼 수 있다.
가변 데이터의 사용은 단일 스레드로 제한하자
객체 참조를 공유하는 행위만 동기화하면서, 한 스레드가 짧은 시간 동안만 데이터 객체를 변경한 후 그 객체 참조를 다른 스레드와 공유하는 것은 수용할 만 하다. 그러면 그 객체가 다시 변경되지 않는 한, 다른 스레드들이 더 이상의 동기화를 하지 않고 그 객체를 읽을 수 있다. 그런 객체를 효율적인 가변 객체(effectively immutable)라 한다. 그리고 그런 객체 참조를 하나의 스레드에서 다른 스레드로 전달하는 것을 안전 출판(safe publication)이라 한다. 객체 참조를 안전하게 출판하는 방법은 많이 있다. 그 객체 참조를 클래스 초기화 시에 static필드에 저장할 수 있고, 또는 정상적으로 객체 락을 사용해서 접근하는 volatile필드나 final필드 및 일반 필드에 저장할 수 있으며, 또는 동시성이 지원되는 컬렉션에 저장할 수도 있다.
요약하면, 여러 스레드가 가변 데이터를 공유할 때, 그 데이터를 읽거나 쓰는 각 스레드에서는 반드시 동기화를 해야한다.
지나친 동기화는 피하자
활동실패와 안전 실패가 생기지 않게 하려면, 동기화 된 메소드나 블록 안에서 절대로 클라이언트한테 제어권을 넘기면 안된다.
동기화된 영역 안에서 외계인 메소드를 절대 호출하지 말자 교착상태와 데이터 손상을 막기 위해서이다.
'JAVA이야기' 카테고리의 다른 글
'10.03.28 story (0) | 2010.04.01 |
---|---|
'10.03.26 story (0) | 2010.04.01 |
'10.03.23 story (0) | 2010.04.01 |
'10.03.22 story (0) | 2010.04.01 |
'10.03.21 story (0) | 2010.04.01 |