Java メモリ モデルではsynchronize
、同じモニター上で同期するブロックが、それらのブロック内で変更された変数に対してビフォア アフター リレーションを強制することが義務付けられています。例:
// in thread A
synchronized( lock )
{
x = true;
}
// in thread B
synchronized( lock )
{
System.out.println( x );
}
この場合x==true
、スレッド A がそのブロックをすでに通過している限り、スレッド B が参照することが保証されますsynchronized
。現在、より柔軟な (そして高速であると言われている) ロックjava.util.concurrent
、特にReentrantReadWriteLock
. したがって、例は次のようになります。
編集:マット bで指摘されているように、コードを誤って変換したため、例が壊れていました。次のように修正されました。
// in thread A
lock.writeLock().lock();
{
x = true;
}
lock.writeLock().unlock();
// in thread B
lock.readLock().lock();
{
System.out.println( x );
}
lock.readLock().unlock();
しかし、メモリー・モデルの仕様の中で、そのようなロックが必要な順序付けを暗示しているというヒントは見たことがありません。実装を調べると、内部の volatile 変数へのアクセスに依存しているようですAbstractQueuedSynchronizer
(少なくとも太陽の実装では)。ただし、これは仕様の一部ではなく、さらに、不揮発性変数へのアクセスは、これらの変数によって与えられるメモリバリアによってカバーされるとは実際には考えられていませんよね?
だから、ここに私の質問があります:
synchronized
「古い」ブロックと同じ順序を想定しても安全ですか?- これはどこかに文書化されていますか?
- volatile 変数にアクセスすると、他の変数のメモリ バリアになりますか?
よろしく、ステフェン
--
やなもんさんへのコメント:
次のコードを見てください。
// in thread a
x = 1;
synchronized ( a ) { y = 2; }
z = 3;
// in thread b
System.out.println( x );
synchronized ( a ) { System.out.println( y ); }
System.out.println( z );
私が理解したことから、メモリバリアは2番目の出力に2を表示するように強制しますが、他の変数への影響は保証されていません...? では、これを volatile 変数へのアクセスとどのように比較できますか?