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