volatile 관련 test 본문

Programming/Java

volatile 관련 test

halatha 2011. 4. 14. 05:01
class TestVolatile
{
	public static void main(String[] args)
	{
		final	int	INTERVAL_TIME	=	15;
		final	BadAtomicLong	bal	=	new BadAtomicLong();
		final	GoodAtomicLong	gal	=	new GoodAtomicLong();
		final	GoodAtomicLong2	gal2	=	new GoodAtomicLong2();

		Thread	t1	=	new Thread(new Runnable() {
			@Override public void run() {
				try {
					while ( true ) {
						Thread.sleep(INTERVAL_TIME);
						bal.getAndSet(1L);
						gal.getAndSet(1L);
						gal2.getAndSet(1L);
					}
				} catch (Exception e) {}
			}
		});
		t1.start();

		Thread	t2	=	new Thread(new Runnable() {
			@Override public void run() {
				try {
					while ( true ) {
						Thread.sleep(INTERVAL_TIME);
						final	long	bVal	=	bal.getValue();
						final	long	gVal	=	gal.getValue();
						final	long	gVal2	=	gal2.getValue();
						if ( bVal != gVal || bVal != gVal2 || gVal != gVal2 )
							System.out.println("t2: " +
								bVal + "\t" + gVal + "\t" + gVal2);
					}
				} catch (Exception e) {}
			}
		});
		t2.start();
	}
}

class BadAtomicLong {
	long	value;
	synchronized void getAndSet(long d) { value += d; }
	long getValue() { return	value; }
}
class GoodAtomicLong {
	volatile long	value;
	void getAndSet(long d) { synchronized (this) { value += d; } }
	long getValue() { return	value; }
}
class GoodAtomicLong2 {
	long	value;
	synchronized void getAndSet(long d) { value += d; }
	synchronized long getValue() { return	value; }
}
/*
synchronized is re-entrant,
meaning same thread can acquire an already held lock mulitple times

synchronized: 해당 block 내의 것을 동기화
volatile: 읽기 전 system memory의 것으로 thread memory의 것을 변경함

위의 BadAtomicLong의 경우 t1에서 getAndSet()을 호출하고
	t2에서 getValue()를 호출하면 t2의 값은
	d가 더해진 것이 나오지 않는 경우가 있음
	system memory의 값으로 thread memory의 값이 변경되지 않기 때문
그래서 GoodAtomicLong의 경우처럼 value를 volatile로 선언하면
	t2에서 getValue()를 호출할 때마다
	system memory의 값으로 갱신하므로 반영이 됨
	getValue()를 synchronized로 선언을 해도 동작은 하겠지만
	performance에서 손해 발생. 값을 쓰는 것이 아닌데도
	동기화를 하므로 해당 시간동안 다른 thread의 접근이 금지되기 때문

$ java TestVolatile
t2: 2062        2061    2061
*/
Comments