JAvaマルチスレッドのvolatileとsynchronized
7361 ワード
package com.chzhao;
public class Volatiletest extends Thread {
private static int count = 0;
public void run() {
count++;
}
public static void main(String[] args) {
Thread threads[] = new Thread[10000];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Volatiletest();
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
}
}
コードは以上のように、出力が10000であることが期待する、そして、count++はスレッドが安全ではないため、出力が10000未満になることが多い.
この問題を解決するためにvolatileキーワードを追加しました.
package com.chzhao;
public class Volatiletest extends Thread {
private volatile static int count = 0;
public void run() {
count++;
}
public static void main(String[] args) {
Thread threads[] = new Thread[10000];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Volatiletest();
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
}
}
修正後、10000ではない値を出力することもよくあります.
synchronized形式に変更されました.コードは次のとおりです.
package com.chzhao;
public class SynchronizedTest extends Thread {
private static int count = 0;
public void run() {
synchronized (LockClass.lock) {
count++;
}
}
public static void main(String[] args) {
Thread threads[] = new Thread[10000];
for (int i = 0; i < threads.length; i++) {
threads[i] = new SynchronizedTest();
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
}
}
package com.chzhao;
public class LockClass {
public static byte[] lock = new byte[0];
}
このように修正する出力は10000である.
これでvolatileというキーワードが全く役に立たないことを説明しますか?synchronizedだけがスレッドの安全を保証できますか?
『Java理論と実践:Volatile変数を正しく使用する』では、
Java™ 言語には、同期ブロック(またはメソッド)とvolatile変数の2つの内在的な同期メカニズムが含まれています.この2つのメカニズムの提案は,コードスレッドのセキュリティを実現するためである.ここで、Volatile変数は同期性が悪い(ただし、より簡単でオーバーヘッドが低い場合がある)ため、エラーが発生しやすい.Java言語のvolatile変数は「程度の軽い
synchronized
」と見なすことができる.synchronized
ブロックに比べてvolatile変数に必要な符号化は少なく、実行時のオーバーヘッドも少ないが、実現できる機能もsynchronized
の一部にすぎない.すなわち、場合によってはsynchronizedよりもvolitileの方が使いやすく、もちろん同期性が悪い.
詳細は『Java理論と実践:Volatile変数を正しく使用する』
参照先:http://www.ibm.com/developerworks/cn/java/j-jtp06197.html