【发布时间】:2015-10-07 22:37:06
【问题描述】:
我目前正在考虑实现一个会话管理器 java 类,该类提供按需读取和刷新会话令牌的功能。如果正在刷新会话令牌(即从服务器获取),则会话令牌读取器应阻塞,直到刷新完成。同样,刷新请求会被阻止,直到任何正在进行的读取都未完成。由于会话令牌读取请求与会话令牌刷新请求相比非常频繁,因此我决定使用 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() 将返回 false,然后获取读锁并阻塞,直到写锁被释放,从而重新调度read-blocked 线程来完成读取。此逻辑适用于多个线程同时调用 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();
}
但是,我对这种方法没有太多经验,也不完全确定它会产生的同步影响,因为我想确保只有一个线程可以获得写锁,并且后续请求会被读取。 任何建议/指针将不胜感激。
【问题讨论】:
-
使
refreshToken()成为synchronized方法可以完成这项工作,然后一次只有一个线程可以访问refreshToken()部分。其他线程将等待当前“在”方法中的线程完成 -
好吧,我想在读者和作者之间同步对会话令牌的访问。此外,类上还会有其他方法,所以我不想通过使这个方法同步来阻塞整个对象。因此使用锁的原因。
标签: java multithreading concurrency locking reentrantreadwritelock