优于ReentrantReadWriterLock的StampedLock

311 阅读2分钟

StampedLock

相当于是对读写锁的性能提升;StampedLock支持三种模式:写锁、悲观读锁和乐观读锁。写锁和悲观读锁和ReadWriterLock的读写锁语义一致;区别在于StampedLock 里的写锁和悲观读锁加锁成功之后,都会返回一个 stamp;然后解锁的时候,需要传入这个 stamp;不支持重入,不支持条件变量condition;

官方使用示例:

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);//a valid write stamp, or zero on failure
         if (ws != 0L) {
           stamp = ws;
           x = newX;
           y = newY;
           break;
         }
         else {
           sl.unlockRead(stamp);
           stamp = sl.writeLock();
         }
       }
     } finally {
       sl.unlock(stamp);
     }
   }
 }

解锁sl.unlock(stamp);

解锁需要传入对应获取锁时返回的stamp

验证乐观读锁是否失效sl.validate(stamp)

/**
 * Returns true if the lock has not been exclusively acquired
 * since issuance of the given stamp. Always returns false if the
 * stamp is zero. Always returns true if the stamp represents a
 * currently held lock. Invoking this method with a value not
 * obtained from {@link #tryOptimisticRead} or a locking method
 * for this lock has no defined effect or result.
 *
 * @param stamp a stamp
 * @return {@code true} if the lock has not been exclusively acquired
 * since issuance of the given stamp; else false
 */

如果自给定stamp发行以来尚未以独占方式获取锁,则返回 true。 如果标记stamp为零,则始终返回 false。 如果stamp代表当前持有的锁,则始终返回 true。 使用不是从tryOptimisticRead获得的值或此锁的锁定方法调用此方法没有定义的效果或结果。

锁升级 sl.tryConvertToWriteLock(stamp);

读锁升级成写锁,释放写锁时需要传入sl.tryConvertToWriteLock(stamp);返回新的stamp;

使用 StampedLock 一定不要调用中断操作,如果需要支持中断功能,一定使用可中断的悲观读锁 readLockInterruptibly() 和写锁 writeLockInterruptibly()