0

我必须搜索一个对象:首先在 aBlockingQueue中,如果它不在那里,那么我需要在 a 中搜索ConcurrentHashMap并需要做一些操作。这需要是线程安全的。

下面的代码可以吗?ConcurrentHashMap是否按预期同步工作?

synchronized(blockingQueue){
   if(!blockingQueue.contains(element)) {        
      synchronized(concurrentHashMap) {    
             //do something
      }
   }
}
4

4 回答 4

2

首先,像您的示例中那样同步可能不会达到您的预期。您必须检查这两个集合的实现,并检查它们是否在自身上同步,而不是在任何其他内部对象上同步。

如果您需要像这样同步访问,我认为使用同步集合是个坏主意。显然,您的关键部分比简单的读/写操作更复杂。考虑使用自定义锁进行操作,如下所示:

final Object lock = new Object();

public void addDataToHashMap(Object param, Object val) {
  synchronized(lock) {
    concurrentHashMap.put(param, val);
  }
}

public void performComplexOperations() {
  synchronized (lock) {
    if (!blockingQueue.contains(element)) {        
      processSomeData(concurrentHashMap);
    }
  }
}
于 2013-08-20T08:23:38.563 回答
1

之前的答案中没有包含的一个重要说明是synchronized(concurrentHashMap)不会锁定哈希映射,并且 `synchronized(blockingQueue)不会锁定队列,它们可以在其他一些未同步的线程中继续更新对象。

引用 ConcurrentHashMap 的 javadoc:

但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。

知道//do something应该做什么来给出更好的答案会很有帮助。

于 2013-08-20T08:37:41.867 回答
0

你能解释更多吗?谁正在访问这些对象blockingQueue 和concurrentHashMap。有只读取/只写入它们的线程吗?

也许你应该看看 java.util.concurrent.locks.ReadWriteLock。

于 2013-08-20T08:15:23.557 回答
0

我想说最好的方法是将此逻辑包装在一个单独的通用函数中,并将其同步到一个通用锁上(例如放置此函数的实用程序类的实例),如下所示:

class MyUtil{

    public synchronized Object getMyObject(){    
        //if not in queue then get from map
        //no need to put any lock on queue or map now
    }
}
于 2013-08-20T08:04:13.703 回答