S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

volatileの検証

くっそーこのテストコードじゃ再現せんぞ。

public class ThreadTest extends Thread {
	
	private int id = 0;
	
	private ThreadTest th = null;
	
	public static void main(String [] args) {
		ThreadTest test = new ThreadTest();
		test.process();
	}
	
	public int getTestId() {
		return this.id;
	}
	
	public void setTestId(int id) {
		this.id = id;
	}
	
	public ThreadTest getThread() {
		return this.th;
	}
	
	public void setThread(ThreadTest th) {
		this.th = th;
	}
	
	public void process() {
		
		System.out.println("process start.");
		
		ThreadTest th = new ThreadTest();
		th.setThread(this);
		th.start();
		
		setTestId(0);
		while (true) {
			if (getTestId() > 0) {
				break;
			}
		}
		
		System.out.println("process finish.");
		
	}
	
	public void run() {
		
		System.out.println("thread start.");		
		
		try {

			// フラグ書き換え
			getThread().setTestId(1);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		System.out.println("thread finish.");		
		
	}

}

自分のPCでも、実際現象が発生するサーバでも正常に動作しやがる。
Windowsコマンドプロンプトから実行したからか?
サービスでJavaが動くときってそんなに違うもんなんか?
ということで、実際のコードのsleepを削除して、volatileを追記してOKなことを確認。


とりあえず実際のコードで試したらこんな結果に。

NG private int id = 0;
OK private volatile int id = 0;
OK private static int id = 0;

static変数にvolatile付けてもOKなんで、Singletonな扱いの変数なんかも含めて、マルチスレッドなアクセスが必要な場合はvolatileを付けるということで。
最適化されても正常に動作せんと意味ないからね。
[関連]http://d.hatena.ne.jp/S_a_k_U/20070707/p3
[関連]http://d.hatena.ne.jp/S_a_k_U/20070706/p1
[関連]http://d.hatena.ne.jp/S_a_k_U/20070617/p2