代码之家  ›  专栏  ›  技术社区  ›  Dmitry Gorbunov

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

  •  11
  • Dmitry Gorbunov  · 技术社区  · 9 年前

    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 方法在获取后始终会看到x和y字段的最新变化 StampedLock#readLock

    当我们打电话时,有没有建立起某种记忆障碍 StampedLock#writeLock , 冲压锁#读锁

    有人能指出文件中关于这一点的引用吗?

    2 回复  |  直到 9 年前
        1
  •  2
  •   Eugene    9 年前

    我说不出为什么文件中没有明确引用这一点——可能是因为它有点隐含,但在内部,它确实起到了作用 Unsafe.compareAndSwapLong 也就是说 LOCK CMPXCHG ,其中 x86 full memory barrier volatile 的确

    实际上,关于 x86 这有一个 lock

        2
  •  2
  •   Luciano van der Veekens    9 年前

    的Javadoc Lock 接口状态如下:

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

    成功的解锁操作与成功的解锁操作具有相同的内存同步效果。

    尽管 StampedLock asReadLock() 即:

    返回此冲压锁的普通锁视图,其中包含锁。lock()方法被映射到readLock(),对于其他方法也是如此。

    它返回一个 的内部类 ReadLockView ,这是 .

    界面