【发布时间】:2011-02-04 07:24:27
【问题描述】:
java meomry 模型要求在同一监视器上同步的synchronize 块对在这些块中修改的变量强制执行前后处理。示例:
// in thread A
synchronized( lock )
{
x = true;
}
// in thread B
synchronized( lock )
{
System.out.println( x );
}
在这种情况下,只要线程 A 已经通过了 synchronized 块,线程 B 就会看到 x==true。现在我正在重写大量代码以使用java.util.concurrent 中更灵活(据说更快)的锁,尤其是ReentrantReadWriteLock。所以这个例子看起来像这样:
EDIT:该示例已损坏,因为我错误地转换了代码,如 matt 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();
但是,我在内存模型规范中没有看到任何暗示这种锁也暗示着必要的排序。查看实现,它似乎依赖于对 AbstractQueuedSynchronizer 中的 volatile 变量的访问(至少对于 sun 实现)。然而,这不是任何规范的一部分,而且对非易失性变量的访问并没有真正考虑由这些变量给出的内存屏障覆盖,是吗?
所以,这是我的问题:
- 假设与“旧”
synchronized块相同的顺序是否安全? - 这是否记录在某处?
- 访问任何 volatile 变量是否是任何其他变量的内存屏障?
问候, 史蒂芬
--
对 Yanamon 的评论:
看下面的代码:
// 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,但不能保证对其他变量产生影响......?那么这如何与访问 volatile 变量相比呢?
【问题讨论】:
-
关于您添加的代码的注释,如果线程 b 在线程 a 之前获得了锁,则线程 b 只会打印 2... 这有点暗示,但我只是想澄清一下。但要回答你 volatile 的问题,请按以下方式使用 volatile 来强制可见性:-------- volatile boolean memoryBarrier = false; int unguardedValue = 0; //线程a: unguardedValue = 10;记忆屏障=真; // thread b if (memoryBarrier) { // unguardedValue 保证读取为 10; }
-
好吧,我猜在 cmets 中编写代码并不能很好地工作,我用一个例子更新了我的答案
标签: java concurrency locking synchronized