2

我有一个Map可以null在应用程序首次启动时清除或简单清除的对象。我需要所有访问此映射的线程阻塞,直到映射初始化,然后我才需要向所有线程发出信号以访问此映射。

Synchronized此映射包含配置数据,除非单个线程决定刷新以加载新的配置数据,否则它将仅用于读取(因此,出于性能考虑,它不需要,因为我也认为没有必要)。我尝试将Condition对象用于 aReentrantLockIllegalMonitorState每当我尝试signalAll()或时它都会引发异常await()

这是我需要做的伪代码:

void monitorThread{
    while(someCondition){
        map = updatedMap();
        condition.signalAll();
    }
}

String readValueFromMap(String key){
    if(map == null){
        condition.await();
    }
    return map.get(key);
}
4

3 回答 3

4

CountDownLatch是你所需要的全部。

CountDownLatch latch = new CountDownLatch(1); 

虽然初始化 hashmaplatch.countdown()并在线程中使用latch.await()

void monitorThread{
    map = updatedMap();
    latch.countDown();
}

String readValueFromMap(String key){
    latch.await();
    return map.get(key);
}

请注意,CountDownLatchawait()方法仅在倒计时大于 0 时才等待,因此只有第一次。

于 2012-09-04T13:40:40.703 回答
3

要做到这一点,您需要一个内存屏障,因此volatile. 由于地图最初可能为空,因此您将需要另一个锁定对象。以下应该有效:

private final Object lockObject = new Object();
private volatile Map<...> map;

void monitorThread{
    while (condition){
        // do this outside of the synchronized in case it takes a while
        Map<...> updatedMap = updatedMap();
        synchronized (lockObject) {
           map = updatedMap;
           // notify everyone that may be waiting for the map to be initialized
           lockObject.notifyAll();
        }
    }
}

String readValueFromMap(String key) {
    // we grab a copy of the map to avoid race conditions in case the map is
    // updated in the future
    Map<...> mapRef = map;
    // we have a while loop here to handle spurious signals
    if (mapRef == null) {
        synchronized (lockObject) {
           while (map == null) {
               // wait for the map to initialized
               lockObject.wait();
           }
           mapRef = map;
        }
    }
    return mapRef.get(key);
}
于 2012-09-04T13:51:56.557 回答
0

听起来您只需要一个“锁定”对象来保护对地图的访问。

这些非常容易使用:

 Lock l = ...;
 l.lock();
 try {
     // access the resource protected by this lock
 } finally {
     l.unlock();
 }

您可能会使用:java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock

于 2012-09-04T13:53:50.973 回答