我正在使用StampedLock实现缓存读取或加载方法,我想知道是否可以比javadoc更好地改编示例。

作者Doug Lea给出了一个“乐观读”示例和一个“将读锁升级为写锁”示例,但是在我的用例中,我想同时做这两个事情。

public String getConverted(String input) {

    String customised = null;
    long stamp = 0L;

    while (customised == null) {
        if (!lock.validate(stamp)) {
            stamp = lock.tryOptimisticRead();
        }
        customised = cached.get(input);

        // if the lock was valid we can trust the value of customised
        if (lock.validate(stamp) && customised == null) {
            long writeStamp = 0L;
            try {
                while (customised == null) {
                    writeStamp = lock.tryConvertToWriteLock(stamp);
                    if (writeStamp != 0L) {
                        stamp = writeStamp;
                        customised = convertToCustom(input);
                        cached.put(input, customised);
                    } else {

                        // so what do we do here (line 15)?

                    }
                }
            } finally {
                lock.unlock(stamp);
            }
        } else {
            // if the lock was invalid, customised could be anything, so:
            customised = null;

            // and what do we do here (line 25)?
        }
    }

    return customised;
}


因此,在算法中我需要做两点-在两种情况下都可以:


获取硬锁-在第15行:

                    lock.unlockRead(stamp);
                    stamp = lock.writeLock();


在第25行:

                    stamp = lock.readLock();

还是什么?

                    Thread.sleep(25);



这对我没有帮助-当然StampedLock可以更好地管理此线程的阻塞!

但是如何?如果我只是调用readLock()writeLock(),那么我就放弃了在StampedLock#tryOptimisticRead()StampedLock#tryConvertToWriteLock()中希望经过良好编码和测试的排队算法。

还是这些方法背后的逻辑已经因为一次失败而被取消了?

最佳答案

您可以看看以下方法以供参考。

tryConvertToWriteLock和tryOptimisticRead中没有排队机制。


  仅当锁定时,方法tryOptimisticRead()才返回非零戳
  当前未处于写入模式。方法validate(long)返回
  如果自获取a后未在写入模式下获取锁,则为true
  给邮票。该模式可以认为是极弱的版本
  读锁的状态,编写者可以随时将其破坏。指某东西的用途
  短只读代码段的乐观模式通常会减少
  竞争并提高吞吐量。但是,它的使用本质上是
  脆弱。乐观的阅读部分应仅阅读字段并保持
  它们放在局部变量中,以供验证后使用。田野阅读
  而在乐观模式下可能会完全不一致,因此适用用法
  仅在您熟悉数据表示形式以进行检查时
  一致性和/或重复调用方法validate()。例如,
  首次读取对象或
  数组引用,然后访问其字段,元素或
  方法。


另外,我喜欢控制流,在其中检查乐观锁定的有效性,如果发现它无效,则获取锁定,因为它避免了代码中使用的“ else”块。

tryConvertToWriteLock的类似代码流。

private final StampedLock sl = new StampedLock();

    /**


    * This method is to show the feature of tryOptimisticRead() method
    */
      public double getTotalRevenueOptimisticRead() {
        long stamp = sl.tryOptimisticRead();
        double balance = this.totalRevenue;
        boolean lockAcquired = false;
        //calling validate(stamp) method to ensure that stamp is valid, if not then acquiring the read lock
        if (!sl.validate(stamp)){
          lockAcquired = true;
          LOG.info("stamp for tryOptimisticRead() is not valid now, so acquiring the read lock");
          stamp = sl.readLock();
        }
        try {
          balance = this.totalRevenue;
        } finally {
          if(lockAcquired){
             sl.unlockRead(stamp);
          }
        }
        return balance;
      }



/**
* This method is to show the feature of tryConvertToWriteLock() method
*/
  public double getStateTaxReturnUisngConvertToWriteLock(TaxPayer taxPayer) {
    double incomeTaxRetunAmount = taxPayer.getTaxAmount() * 5/100;
    long stamp = sl.readLock();
    boolean lockAcquired = false;
    //Trying to upgrade the lock from read to write
    stamp = sl.tryConvertToWriteLock(stamp);
    //Checking if tryConvertToWriteLock got success otherwise call writeLock method
    if(stamp == 0L){
      LOG.info("stamp is zero for tryConvertToWriteLock(), so acquiring the write lock");
      stamp = sl.writeLock();
      lockAcquired = true;
    }
    try {
      this.totalRevenue -= incomeTaxRetunAmount;
    } finally {
      if(lockAcquired){
         sl.unlockWrite(stamp);
      }
    }
    return incomeTaxRetunAmount;
  }

09-28 07:03