java - 为什么我们不需要带有 StampedLock 的 volatile?

标签 java multithreading java-8 volatile memory-barriers

给定来自 Oracle 文档的代码示例 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/StampedLock.html

class Point {
   private double x, y;
   private final StampedLock sl = new StampedLock();

   void move(double deltaX, double deltaY) { // an exclusively locked method
     long stamp = sl.writeLock();
     try {
       x += deltaX;
       y += deltaY;
     } finally {
       sl.unlockWrite(stamp);
     }
   }

   double distanceFromOrigin() { // A read-only method
     long stamp = sl.tryOptimisticRead();
     double currentX = x, currentY = y;
     if (!sl.validate(stamp)) {
        stamp = sl.readLock();
        try {
          currentX = x;
          currentY = y;
        } finally {
           sl.unlockRead(stamp);
        }
     }
     return Math.sqrt(currentX * currentX + currentY * currentY);
   }

   void moveIfAtOrigin(double newX, double newY) { // upgrade
     // Could instead start with optimistic, not read mode
     long stamp = sl.readLock();
     try {
       while (x == 0.0 && y == 0.0) {
         long ws = sl.tryConvertToWriteLock(stamp);
         if (ws != 0L) {
           stamp = ws;
           x = newX;
           y = newY;
           break;
         }
         else {
           sl.unlockRead(stamp);
           stamp = sl.writeLock();
         }
       }
     } finally {
       sl.unlock(stamp);
     }
   }
 }

并且假定类 Point 的所有方法都可以从不同的线程调用:

为什么我们不需要将字段 x 和 y 声明为 volatile?

是否保证执行 Point#moveIfAtOrigin 方法的代码在获取 StampedLock#readLock 后总是看到 x 和 y 字段的最新变化?

当我们调用 StampedLock#writeLockStampedLock#readLock 时,是否会建立任何类型的内存屏障?

谁能指出与此相关的文档中的引述?

最佳答案

我不知道为什么没有在文档中明确引用 - 可能是因为它有点隐含,但在内部执行 Unsafe.compareAndSwapLong 转换为 LOCK CMPXCHG ,在 x86 上有 full memory barrier(我假设类似的事情在其他平台上完成);所以确实不需要那些volatile

实际上,x86 上任何具有lock 的指令都将具有完整的内存屏障。

关于java - 为什么我们不需要带有 StampedLock 的 volatile?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45956249/

相关文章:

java - 没有为与上下文路径 [/Struts2Application] 关联的 namespace [/] 和操作名称 [LoginClass] 映射的操作。 - [未知位置]

java - 如何抛出错误并同时返回空列表?

Java多线程: Implementing of important methods in Thread class in Native Libraries?

java - 如何使用 Java 8 在 Spring 4 中执行 queryForList?

java - Junit ExpectedException 失败并显示解释性消息

java - 通过比较堆栈和队列确定回文

java - 对象锁定和类级别锁定

python - 方法的 "self"参数是否受到某种保护?

java - 使用 Java 8 5 天编译用 Java 编写的旧程序

java - 为什么 Double::compareTo 可以作为 Stream.max(Comparator<?super T>comparator) 的参数