12

同期を使用すると、パフォーマンスに影響があります。volatile を synchronized と組み合わせて使用​​して、パフォーマンスのオーバーヘッドを削減できますか? たとえば、Counter のインスタンスは多くのスレッド間で共有され、各スレッドは Counter のパブリック メソッドにアクセスできます。以下のコードでは、volatile が getter に使用され、synchronized が setter に使用されます。

public class Counter
{
    private volatile int count;

    public Counter()
    {
        count = 0;
    }

    public int getCount()
    {
        return count;
    }

    public synchronized void increment()
    {
        ++count;
    }   
}

これが壊れる可能性のあるシナリオを教えてください。

4

4 に答える 4

11

はい、間違いなくできます。実際、 のソース コードを見るとAtomicInteger、それが本質的に彼らが行っていることです。AtomicInteger.getを返すだけvalueで、これはvolatile int(リンク) です。あなたが行ったことと彼らがしていることとの唯一の本当の違いは、同期の代わりにインクリメントに CAS を使用することです。最新のハードウェアでは、CAS によって相互排除を排除できます。古いハードウェアでは、JVM はインクリメントの周りにある種のミューテックスを配置します。

揮発性読み取りは不揮発性読み取りとほぼ同じくらい高速であるため、読み取りは非常に高速です。

それだけでなく、volatileフィールドがティアリングされないことが保証されています。JLS 17.7volatile longを参照してください。これは、 s およびdoubles がワード ティアリングの影響を受けないことを指定しています。したがって、コードは とlong同様に動作しintます。

Diego Frehner が指摘しているように、インクリメントが発生する「直後」に値を取得すると、インクリメントの結果が表示されない可能性があります。つまり、前または後のいずれかが表示されます。もちろん、get同期された場合は、読み取りスレッドからまったく同じ動作が得られます。つまり、増分前または増分後の値が表示されます。だから本当にどっちも同じ。言い換えれば、それが起こっているときに価値が見えないと言うのは意味がありません-(a)あなたが得られず、(b)あなたが決して望んでいない言葉の引き裂きを意味していない限り.

于 2012-07-27T05:03:39.017 に答える
6

1.私は個人的にvolatile と組み合わせて このメカニズムを使用しましsynchronizedた。

2.単独で使用 すると常に一貫した結果が得られますがsynchronized、単独で使用しても常に同じ結果が得られるわけではありません。 volatile

3.これは、volatile キーワードが同期プリミティブではないためです。スレッドでの値のキャッシュを防止するだけですが、2 つのスレッドが同じ値を変更して同時に書き戻すことを防止するものではありません。

4. lock なしでスレッドへの同時アクセスを許可しますvolatileが、使用すると、1 つのスレッドのみがこれとクラス内のすべての同期メソッドにアクセスできるようになります。synchronized

5.両方を使用 するとvolatile and synchronized、これが行われます....

volatile -変更された値をスレッドに反映し、キャッシュを防止します。

synchronized -ただし、synchronized キーワードを使用すると、1 つのスレッドのみがクラスの同期メソッドにアクセスできるようになります。

于 2012-07-27T04:46:41.530 に答える
0

getCount() を呼び出すと、常に最も実際のカウントが得られるとは限りません。AtomicInteger が適切な場合があります。

于 2012-07-27T04:15:25.533 に答える
0

There wouldn't be a performance gain from using both. Volatile guarantees that the value of a variable will be consistent when reading/writing to the variable across threads executing in parallel by preventing caching. Synchronized, when applied to a method (as you do in your example), only allows a single thread to enter that method at a time and blocks others until execution is complete.

于 2012-07-27T04:18:34.707 に答える