我必须搜索一个对象:首先在BlockingQueue
中,如果它不在那里,那么我需要在ConcurrentHashMap
中搜索并需要进行一些操作。这需要是线程安全的。
下面的代码是否正常?是否按预期在ConcurrentHashMap
上进行同步?
synchronized(blockingQueue){
if(!blockingQueue.contains(element)) {
synchronized(concurrentHashMap) {
//do something
}
}
}
答案 0 :(得分: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);
}
}
}
答案 1 :(得分:1)
以前的答案中未包含的一个重要说明是synchronized(concurrentHashMap)
将不锁定哈希映射,并且`synchronized(blockingQueue)将不锁定队列,它们可以继续在同一个对象上未同步的其他线程中更新。
引用ConcurrentHashMap的javadoc:
但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且没有任何支持以阻止所有访问的方式锁定整个表。
了解//do something
应该做些什么来提供更好的答案会很有帮助。
答案 2 :(得分: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
}
}
答案 3 :(得分:0)
你能解释一下吗?谁正在访问那些对象blockingQueue和concurrentHashMap。有些线程只能读取/只写入它们吗?
也许你应该看看java.util.concurrent.locks.ReadWriteLock。