等待读锁?

时间:2015-10-27 16:39:25

标签: java multithreading concurrency

如何在检查之前等待锁定?

基本上,我想在私有变量中缓存一个列表。我每隔一段时间只填充一次该列表,其他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的东西。我不确定是否应该使用某种sychronizedReadWriteLockReentReadWriteLockLock

我想我已经解释得这么好了。如果我需要澄清任何事情,请告诉我。我可能正在接近这个完全错误。

3 个答案:

答案 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();

所以我认为这就是你需要的东西