14. 쓰레드
동시성 문제 - 동기화
주 메모리
object
a := 2
lock
Thread 1
바이트 코드
실행 엔진
작업 메모리
a := 2
1. 작업
메모리에
복사한다.
Thread
바이트 코드
실행 엔진
작업 메모리
a := 1
주 메모리
object
a := 1
lock
Thread1
바이트 코드
실행 엔진
작업 메모리
a := 1
주 메모리
object
a := 2
Thread 2
바이트 코드
실행 엔진
lock
2. a를
읽어서
값을
바꾼다.
1. 작업
메모리에
복사한다.
Thread 2
바이트 코드
실행 엔진
작업 메모리
a := 1
작업 메모리
a := 2
if (a > 0)
{
a--;
}
주메모리 Object 내용
2. a를
읽어서
값을
바꾼다.
3. 쓰레드
종료시점
에 동기화
주 메모리
object
a := 1
lock
Thread 2
바이트 코드
실행 엔진
작업 메모리
a := 1
3. 쓰레드
종료시점
에 동기화
15. 쓰레드
동시성 문제
심각성
일반 개발 환경인 단일 프로세서 환경에서는 잘 드러나지 않는다.
다중 프로세서가 장착된 운영 환경에 가서야 드러나는 경우가 많다.
부하가 적을 때는 드러나지 않기 때문에 재현하기 쉽지 않다.
해결하기 아주 힘든
문제가 된다.
16. 쓰레드
동시성 문제 - 사례
public void put(Object values)
{
int count = 1;
while (true)
{
if ( )
{
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
e.printStackTrace();
MsgParameter msp = new MsgParameter();
msp.add(poolType);
throw new FWRuntimeException(FWExceptionCode.EX00075, msp, e);
}
count++;
// 객체풀이 여유가 없을 경우 최대 시도 횟수만큼 재시도하고
// 재시도 후에도 여유가 없을 경우는 풀의 맨처음 객체를 제거한다.
if (count == retryCount)
{
if(this.objPool.size()>0)
{
this.objPool.remove(0);
}
}
continue;
}
this.objPool.add(values);
break;
}
}
17. 쓰레드
쓰레드 안정성을 보장하라.
JVM 차원 필드 동기화 : volatile – 정확히 동작하지 않음
코드 차원 동기화 : synchronized – 동시성 VS 정합성
객체 공유하지 않기 : 참조 넘기지 않기
불변 객체 만들기 : singleton
18. 쓰레드
synchronized
synchronized로 구분된 블락은 특정 시점에 오직 한 쓰레드만 실
행할 수 있다.
주메모리와 작업메모리 내용을 동기화해서 한 쓰레드가 바꾼 상
태를 다른 쓰레드가 알아차리게 한다.
Oracle select … for update와 비슷하다.
20. 쓰레드
Synchronized
동기화는 성능을 크게 저하시킨다. 꼭 필요할 때만 동기화하라.
final public class ServiceLocator
{
private Context ctx;
private static ServiceLocator SINGLETON;
private ServiceLocator()
{
this.ctx = new InitialContext();
…
}
public static synchronized ServiceLocator getInstance()
{
if (SINGLETON == null)
{
SINGLETON = new ServiceLocator();
}
return SINGLETON;
}
…
}
동기화가 필요할까?
[YES] 객체가 한 번만 생성된다는
것을 보장하려면 동기화는 필요하다.
[NO] 아주 빈번하게 호출되는
메소드를 동기화하면 전체 시스템
성능에 영향을 준다.