2013-05-20 3 views
10

は、あなたがこのコードを持って言う:Java同期ブロックでは、書き込みはすべてのフィールドで表示されるのか、同期変数だけで表示されますか?

private String cachedToken; 
private final Object lockObject = new Object(); 

.... 


retrieveToken(){ 
synchronized(lockObject){ 
    if (cachedToken == null){ 
    cachedToken = goGetNewToken(); 
    } 
    return cachedToken; 
} 
} 

cachedTokenへの書き込みはlockObjectにロックされているすべてのスレッドに対して可視になりますか?

+0

はい、それはポイントです...しかし、書き込みはCPUのl1またはl2キャッシュに起こり、別のスレッドがロックを獲得する前にメインメモリにフラッシュされません。 –

+0

それは当てはまりません。別のスレッドが別のスレッドが書き込みを行った後に別のスレッドが 'lockObject'をロックした場合、スレッドには書き込みが見えます。 –

+0

注: "同期変数"への書き込みは頻繁に*不良*です。コードは変数ではなくオブジェクト上で同期されます。変数が途中で異なるオブジェクトを参照するように変更された場合、その変数が参照するオブジェクトで同期化された複数のブロックが同時に実行される可能性があります。 –

答えて

7

はい。 lockObjectを同期させると、Happen Before Relationship(別名メモリバリア)が確立されます。これは、後でロックを取得するすべてのスレッドに、ロックが以前に保持されている間に発生した変更がすべて表示されることを意味します。

ただし、遅延初期化の実装には問題があります。これは適切な方法です:

この方法では、スレッドが最初にスレッドの要求を開始するときに、少しだけロックを取得するだけです。その後、cachedTokenはnullにならず、同期する必要はありません。

  • 不可分例えば一方
  • オブジェクト全体のメモリ・バリア(あなたがあなたのケースに期待するもの)

volatileメモリバリアを確認してください。もちろん

+0

そのメモリバリアには、同期したオブジェクトだけでなく、タッチされたフィールドも含まれますか? –

+0

@Tom McIntyreあなたのやり方は実際には危険です。これを見てください:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html – Mik378

+1

そうでなければ、共有状態の並行処理は既にそれよりも難しいでしょう! –

5

synchronize二つのことを保証しますアトミック性は扱いません。

+0

読み書きとは別にlongsやdoubleへの書き込みとは別に、volatileではDOが原子性を保証します。 –

+0

@Tom McIntyreはい、しかし、それは 'volatile'キーワード自体のせいではありません。 – Mik378

+0

「揮発性のキーワードそのものではない」ということはどういう意味ですか? –

関連する問題