簡體   English   中英

為什么我們不需要與StampedLock揮發?

[英]Why don't we need volatile with StampedLock?

給出來自Oracle docs的代碼示例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 ,它在x86full memory barrier (我假設像這是在其他平台上完成的); 所以沒有必要確實那些volatile

實際上, x86上有lock任何指令都會有一個完整的內存屏障。

Lock接口的Javadoc聲明如下:

內存同步

所有Lock實現必須強制執行內置監視器鎖提供的相同內存同步語義,如Java語言規范(17.4內存模型)中所述:

成功的鎖定操作具有與成功鎖定操作相同的內存同步效果。 成功解鎖操作具有與成功解鎖操作相同的內存同步效果。 不成功的鎖定和解鎖操作以及重入鎖定/解鎖操作不需要任何內存同步效果。

即使StampedLock沒有實現Lock ,它也有像asReadLock()這樣的方法:

返回此StampedLock的普通Lock視圖,其中Lock.lock()方法映射到readLock(),對於其他方法也是如此。

它返回StampedLock的內部類ReadLockView的實例,它是Lock的實際實現。

但是因為它只是一個委托者,這意味着原始方法必須創建內存屏障才能符合Lock接口的內存同步實施。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM