Java マルチスレッドでの volatile および synchronized の使用状況分析

高洛峰
リリース: 2017-01-05 16:02:51
オリジナル
1787 人が閲覧しました

この記事では、Java マルチスレッドにおける volatile および synchronized の使用法を例とともに分析します。皆さんの参考に共有してください。具体的な実装方法は以下の通りです:

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以外の値が出力されることが多いです。

同期形式に変更されたコードは次のとおりです:

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 キーワードがまったく役に立たないことを意味しますか?スレッドの安全性を確保できるのは同期のみですか?

説明:

Java 言語には、同期ブロック (またはメソッド) と揮発性変数という 2 つの固有の同期メカニズムが含まれています。どちらのメカニズムもコード スレッドの安全性を実現するために提案されています。揮発性変数は同期性が低く (ただし、より単純でコストが低い場合もあります)、その使用はエラーも発生しやすくなります。 Java 言語の揮発性変数は、同期ブロックに比べて「同期性が低い」と考えることができます。揮発性変数は必要なコーディングが少なく、実行時のオーバーヘッドも少なくなりますが、機能は同期化の一部にすぎません。

つまり、場合によっては、同期よりも揮発性の方が使いやすいですが、もちろん同期は悪くなります。

この記事が皆さんの Java プログラミングに役立つことを願っています。

Java マルチスレッドにおける揮発性および同期された使用状況分析に関するその他の記事については、PHP 中国語 Web サイトに注目してください。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート