首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java中的StampedLock是什么?

Java中的StampedLock是什么?
EN

Stack Overflow用户
提问于 2014-09-29 07:03:59
回答 3查看 15K关注 0票数 32

我正在编写Java代码,我需要在其中实现线程。我正在浏览Java8API,并逐渐了解了盖章锁的情况。有人能告诉我为什么在多线程中使用StampedLocks吗?

提前谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-29 13:20:45

StampedLock是使用ReadWriteLock (由ReentrantReadWriteLock实现)的替代方案。StampedLock和ReentrantReadWriteLock的主要区别是:

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

因此,如果您的场景中有争用(否则您也可以使用synchronized或简单的Lock)和更多的读取器而不是作者,那么使用StampedLock可以显著提高性能。

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

海因茨·卡布茨写过关于StampedLocks 在他的通讯里的文章,他还创作了关于性能的介绍

票数 33
EN

Stack Overflow用户

发布于 2014-09-30 17:58:28

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

StampedLocks被设计为用于开发线程安全组件的内部实用程序.它们的使用依赖于它们所保护的数据、对象和方法的内部属性的知识。它们不是可重入的,因此锁定的主体不应该调用其他可能试图重新获取锁的未知方法(尽管您可以将邮票传递给其他可以使用或转换它的方法)。读取锁模式的使用依赖于相关的代码部分是无副作用的.未经验证的乐观读取部分不能调用不知道可以容忍潜在不一致的方法。邮票使用有限的表示,并且不是密码安全的(例如,有效的邮票可以猜测)。邮票价值可在(不早于)一年连续运行后循环使用。没有使用或验证时间超过此期限的邮票可能无法正确验证。StampedLocks是可序列化的,但总是反序列化为初始的未锁定状态,因此它们对远程锁定没有用处。

例如-

代码语言:javascript
运行
复制
 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);
     }
   }
 }
票数 5
EN

Stack Overflow用户

发布于 2019-04-19 14:00:53

除了@assylias 回答

StampedLock支持使用方法tryConvertToWriteLock(long)将readLock升级到writeLock

爪哇文档

该类还支持有条件地提供跨三种模式的转换的方法。例如,方法tryConvertToWriteLock(long)试图“升级”一个模式,如果(1)已经在读模式中处于写入模式(2),并且没有其他读取器,或者(3)处于乐观模式,并且锁可用,则返回有效的写入标记。这些方法的形式是为了帮助减少在基于重试的设计中出现的一些代码膨胀。

代码样本:

代码语言:javascript
运行
复制
class Point {
   private double x, y;
   private final StampedLock sl = new StampedLock();

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

   // a read-only method
   // upgrade from optimistic read to read lock
   double distanceFromOrigin() {
     long stamp = sl.tryOptimisticRead();
     try {
       retryHoldingLock: for (;; stamp = sl.readLock()) {
         if (stamp == 0L)
           continue retryHoldingLock;
         // possibly racy reads
         double currentX = x;
         double currentY = y;
         if (!sl.validate(stamp))
           continue retryHoldingLock;
         return Math.hypot(currentX, currentY);
       }
     } finally {
       if (StampedLock.isReadLockStamp(stamp))
         sl.unlockRead(stamp);
     }
   }

   // upgrade from optimistic read to write lock
   void moveIfAtOrigin(double newX, double newY) {
     long stamp = sl.tryOptimisticRead();
     try {
       retryHoldingLock: for (;; stamp = sl.writeLock()) {
         if (stamp == 0L)
           continue retryHoldingLock;
         // possibly racy reads
         double currentX = x;
         double currentY = y;
         if (!sl.validate(stamp))
           continue retryHoldingLock;
         if (currentX != 0.0 || currentY != 0.0)
           break;
         stamp = sl.tryConvertToWriteLock(stamp);
         if (stamp == 0L)
           continue retryHoldingLock;
         // exclusive access
         x = newX;
         y = newY;
         return;
       }
     } finally {
       if (StampedLock.isWriteLockStamp(stamp))
         sl.unlockWrite(stamp);
     }
   }

   // Upgrade read lock to write lock
   void moveIfAtOrigin(double newX, double newY) {
     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);
     }
   }
 }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26094200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档