Java中的StampedLock是什么?

2022-09-01 09:53:03

我正在编写Java代码,我需要在其中实现线程。我正在浏览JAVA 8 API,我开始了解冲压锁。谁能告诉我为什么要在多线程中使用StampedLocks?

提前致谢。


答案 1

StampedLock是使用ReadWriteLock(由ReentrantReadWriteLock实现)的替代方法。StampedLock和ReentrantReadWriteLock之间的主要区别在于:

  • StampedLocks 允许对读取操作进行乐观锁定
  • 重入锁是重入的(StampedLock 不是)

因此,如果您有一个场景,其中您有争用(否则您可能最好使用或简单)并且更多的读者而不是编写器,则使用StampedLock可以显着提高性能。synchronizedLock

但是,在得出结论之前,您应该根据自己的特定用例来衡量性能。

Heinz Kabutz在他的时事通讯中写了关于StampedLocks的文章,他还做了一个关于表演的演讲


答案 2

java.util.concurrent.locks.StampedLock 的 API 文档说:

StampedLocks设计用于在开发线程安全组件时用作内部实用程序。它们的使用依赖于对它们所保护的数据、对象和方法的内部属性的了解。它们不是可重入的,因此锁定的主体不应调用其他可能尝试重新获取锁的未知方法(尽管您可以将标记传递给可以使用或转换它的其他方法)。读锁定模式的使用依赖于关联的代码段是否无副作用。未经验证的乐观读取部分不能调用已知无法容忍潜在不一致的方法。邮票使用有限的表示形式,并且在加密上是不安全的(即,有效的邮票可能是可猜测的)。印章值可在连续运行一年后(不早于)回收利用。未经使用或验证而持有超过此期限的邮票可能无法正确验证。StampedLock 是可序列化的,但始终反序列化为初始解锁状态,因此它们对于远程锁定没有用处。

例如 -

 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);
     }
   }
 }