Java内存模型:重新排序和并发锁

Ste*_*eil 8 java concurrency locking synchronized

java meomry模型要求synchronize在同一监视器上同步的块强制执行在这些块中修改的变量之前的实现.例:

// in thread A
synchronized( lock )
{
  x = true;
}

// in thread B
synchronized( lock )
{
  System.out.println( x );
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下x==true,只要线程A已经传递了synchronized-block ,就可以保证线程B将会看到.现在我正在重写大量代码以使用更灵活(并且被称为更快)的锁java.util.concurrent,尤其是ReentrantReadWriteLock.所以这个例子看起来像这样:

编辑:示例被打破,因为我错误地改变了代码,如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();
Run Code Online (Sandbox Code Playgroud)

但是,我没有在内存模型规范中看到任何提示,这种锁也意味着需要订购.查看实现,它似乎依赖于对内部的volatile变量的访问AbstractQueuedSynchronizer(至少对于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 );
Run Code Online (Sandbox Code Playgroud)

从我的理解,内存屏障强制第二个输出显示2,但没有保证影响其他变量......?那么如何将其与访问volatile变量进行比较呢?

Dir*_*irk 5

API-doc:

所有Lock实现必须强制执行内置监视器锁提供的相同内存同步语义,如Java语言规范,第三版(17.4内存模型)中所述:

* A successful lock operation has the same memory synchronization effects as a successful Lock action.
* A successful unlock operation has the same memory synchronization effects as a successful Unlock action.
Run Code Online (Sandbox Code Playgroud)

不成功的锁定和解锁操作以及重入锁定/解锁操作不需要任何内存同步效果.