如何在检查之前等待锁定?
基本上,我想在私有变量中缓存一个列表。我每隔一段时间只填充一次该列表,其他99.999999%的时间,我想读它,所以每次读书时我都不想锁定。
public class SomeServlet extends CustomServlet {
private static Object locker;
private static List<String> someList;
// moderately heavy populate, not called very often
private void populateList() {
// lock
someList.clear();
someList.addAll(getTheListStuff());
// unlock
}
public void doGetLikeMethod(HttpServletRequest req, HttpServletResponse res) {
// looking at some sort of method to check for the lock
// and wait for it, preferably with a timeout
if(!locker.isLocked(1000) && somelist.isEmpty()) {
populateList();
}
// the lock is present far less than 0.01% of the time this is checked
}
public void updateSomeList() {
populateList(); // populate list for some other reason
}
}
这是在servlet中,并没有使用公共框架。我们的领导是非常保护添加任何额外的库,所以我想尽可能避免这种情况。我们有所有apache和java.util的东西。我不确定是否应该使用某种sychronized
,ReadWriteLock
,ReentReadWriteLock
或Lock
。
我想我已经解释得这么好了。如果我需要澄清任何事情,请告诉我。我可能正在接近这个完全错误。
答案 0 :(得分:2)
使用java.util.concurrent.locks.ReentrantReadWriteLock
。只要没有写入,多个线程就可以一次保持读锁定,因此它满足您的效率需求。只有一个线程可以一次保存写锁,并且只有当没有线程保持读锁时才能保持写锁,这样才能确保写和读之间的一致性。您可能希望设置公平性,以便写入线程最终能够进行写入,即使存在持续的读取争用。
答案 1 :(得分:1)
如果您的写作较少且阅读量较多,则可以使用Copy on Write方法。
我用我提到的解决方案重新编写了代码。
public class SomeServlet extends CustomServlet {
private volatile List<String> someList;
// moderately heavy populate, not called very often
private void populateList() {
someList = getTheListStuff();
}
public void doGetLikeMethod(HttpServletRequest req, HttpServletResponse res) {
if(someList == null) {
//If updating is expensive and do not want to do twice in worst case include the synchronization and another if check.
//If updating is not expensive ignore synchronization and nested if.
synnchroized(this){
if(someList == null) {
populateList();
}
}
}
}
public void updateSomeList() {
populateList(); // populate list for some other reason
}
}
答案 2 :(得分:1)
来自http://tutorials.jenkov.com/
允许线程锁定ReadWriteLock的规则 无论是阅读还是写保护资源,如下:
读取锁定如果没有线程锁定ReadWriteLock进行写入, 没有线程请求写锁(但尚未获得)。 因此,多个线程可以锁定锁以进行读取。
写锁定如果 没有线程在读或写。因此,一次只能有一个线程 可以锁定写入锁。
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
readWriteLock.readLock().lock();
// multiple readers can enter this section
// if not locked for writing, and not writers waiting
// to lock for writing.
readWriteLock.readLock().unlock();
readWriteLock.writeLock().lock();
// only one writer can enter this section,
// and only if no threads are currently reading.
readWriteLock.writeLock().unlock();
所以我认为这就是你需要的东西