java - StampedLock#tryOptimisticRead() 实现

标签 java multithreading concurrency

我正在使用 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;
}

因此,算法中有两点我需要做一些事情 - 在这两种情况下:

  1. 获取硬锁 - 第 15 行:

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

    第 25 行:

                        stamp = lock.readLock();
    
  2. 或者什么?

                        Thread.sleep(25); 
    

这对我来说并不合适 - 当然 StampedLock 可以更好地管理该线程上的阻塞!

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

或者这些方法背后的逻辑是否已经因为失败一次而被放弃?

最佳答案

您可以引用以下方法。

tryConvertToWriteLock 和 tryOptimisticRead 中没有排队机制。

Method tryOptimisticRead() returns a non-zero stamp only if the lock is not currently held in write mode. Method validate(long) returns true if the lock has not been acquired in write mode since obtaining a given stamp. This mode can be thought of as an extremely weak version of a read-lock, that can be broken by a writer at any time. The use of optimistic mode for short read-only code segments often reduces contention and improves throughput. However, its use is inherently fragile. Optimistic read sections should only read fields and hold them in local variables for later use after validation. Fields read while in optimistic mode may be wildly inconsistent, so usage applies only when you are familiar enough with data representations to check consistency and/or repeatedly invoke method validate(). For example, such steps are typically required when first reading an object or array reference, and then accessing one of its fields, elements or methods.

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

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

关于java - StampedLock#tryOptimisticRead() 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50158850/

相关文章:

java - 无法加载类 'org.gradle.internal.impldep.com.google.common.collect.Lists'

multithreading - Windows Server 2003上的多线程应用程序中的访问冲突

java - 在线程之间共享资源,不同 java 版本中的不同行为

java - ExecutorService.invokeAll 与 Future.get 每个结果的区别

java - SQL 查询保证返回空

java - org.springframework.data.repository.Repository 类型无法解析。它是从所需的 .class 文件间接引用的

java - 为什么 Java 通常被拼写为 JAVA(通常在旧文本中)?

multithreading - 为什么使用 Receiver<Job> 声明接收者?

concurrency - 计算/显示事件 goroutine 的数量

java - 使用 RxJava fork 任务并合并结果