同步对两个不同对象的访问

时间:2013-08-20 07:57:44

标签: java synchronization concurrenthashmap blockingqueue

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

下面的代码是否正常?是否按预期在ConcurrentHashMap上进行同步?

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

4 个答案:

答案 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。