可重入读写锁同步上是 Write Locked

Reentrant readwrite lock synchronization on isWriteLocked

我目前正在考虑实施会话管理器 java class,它提供按需读取和刷新会话令牌的功能。如果正在刷新会话令牌(即从服务器获取),则会话令牌读取器应阻塞,直到刷新完成。类似地,刷新请求被阻止,直到任何正在进行的读取未完成。由于与会话令牌刷新请求相比,会话令牌读取请求非常频繁,因此我决定使用 ReentrantReadWriteLock 来实现读取和刷新之间的同步。外观如下:

  String refreshToken() {
         try{
             if (readWriteLock.writeLock().trylock()) {
                 //fetch session from server and store on disk
             }
        } finally {
              readWriteLock.writeLock().unlock();  
        }
        return readToken();
    }

   String readToken() {
         try {
         readWriteLock.readLock().lock();
         //read token from disk
         } finally {
               readWriteLock.readLock().unlock();
         }
    return token;
    }

}

我的第一次尝试是在写锁上使用 tryLock(),这样如果它已经被写锁定,tryLock() 将 return false 然后获取一个读锁并阻塞直到写锁被释放从而重新安排读阻塞的线程来完成读。此逻辑适用于多个线程同时调用 refreshSession() 的情况,从而只允许一个线程启动会话令牌刷新,而所有其他线程失败并阻塞在读锁上。

但是,如果一个线程刚刚获得读锁(通过调用 readToken())而另一个线程调用 refreshToken() 来获得写锁,则上述逻辑将失败 - 在这种情况下,tryLock() 将失败结果错过了刷新请求。

作为替代方案,我查看了 readWriteLock.isWriteLocked() 方法,该方法检查是否有任何线程已获取写锁:

String refreshToken() {
    try{
        if (!readWriteLock.isWriteLocked()) {
            readWriteLock.writeLock().lock();
            //fetch session from server and store on disk
        } finally{
              readWriteLock.writeLock().unlock();  
        }
    }
    return readToken();
}

但是,我对这种方法没有太多经验,也不完全确定它会产生的同步影响,因为我想确保只有一个线程可以获得写锁,而后续请求会落入读操作。 任何建议/指点将不胜感激。

您可以在那里介绍新的 ReentrantLocktryLock。 ReentrantLock 承诺只有一个写入者,如果存在写入者则很快失败。

ReentrantLock lock = new ReentrantLock();

public String refreshToken() {
    if (lock.tryLock()) {
        readWriteLock.writeLock().lock();
        try {
            // fetch session from server and store on disk
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }
    return readToken();
}

所以只有一个线程会尝试写入。并且在进行写入时没有线程可以读取。