Java - 同步对象/块

时间:2012-07-09 18:43:16

标签: java synchronization

我正在寻找有关同步块的说明。考虑这个类 -

public class A{
Map map;

 public getValue(String key){
  return map.get(key);
 }

 public remove(String key){
  synchronized(map){
   map.remove(key);
  }
 }
}

A是单身人士。多个线程在整个应用程序中大量访问getValue。我正在添加一个新方法,删除,从地图中删除一个键。如果删除如上所述,

  1. 当一个线程在remove方法的synchronized块中时,我假设它将获取一个地图对象的锁。这是否意味着其他线程试图通过getValue方法访问地图将被阻止? (我希望他们。)
  2. 如果remove方法的synchronized方块中没有线程,那么访问getValue方法的线程是否会照常运行,即不会相互阻塞? (我也喜欢这样)。
  3. 我希望只有在执行删除操作的线程时才阻止getValue线程。

6 个答案:

答案 0 :(得分:4)

  

当一个线程在remove方法的synchronized块中时,我认为它将在map对象上获得一个锁。这是否意味着其他线程试图通过getValue方法访问地图将被阻止?

没有。这意味着你遇到了问题,除非你碰巧使用线程安全的地图实现。

  

如果remove方法的synchronized方块中没有线程,那么访问getValue方法的线程是否会照常运行,即不会相互阻塞? (我也喜欢这样)。

他们不会互相阻挠,不。同样,你需要确保使用你正在使用的Map实现是可以的,尽管它可能可能比在写作的同时阅读更好。

您应该考虑使用ConcurrentMap实施(例如ConcurrentHashMap),此时您根本不需要任何同步。

如果你不能使用它,我建议在同步 getValueremove - 以及测量性能。获得无竞争锁定相当便宜 - 你真的需要无锁吗? (当然,使用ConcurrentHashMap是避免此问题的一种非常简单的方法,但是在开始微优化之前,您应该始终考虑是否需要额外的复杂性来实现所需的性能。 )

答案 1 :(得分:4)

如果我正确理解了您的需求,您可以查看ConcurrentMap,当然还有ConcurrentHashMap,我相信它是在Java 5.0中引入的,并且支持并发级别。

答案 2 :(得分:1)

您没有显示如何实例化Map实例,但假设它不是一个线程安全的集合实例,则此代码是线程安全的。

答案 3 :(得分:0)

<强> 1。 getValue()不同步,当一个线程获取一个对象的锁时,它可以控制所有同步的块...而不是非同步的块......  所以其他线程可以在线程处于同步(映射)块时访问getValue()

<强> 2。使用HashTable,这是一个同步MAP

答案 4 :(得分:0)

你有鸡和蛋的问题

  

我希望只有在执行删除操作的线程时才阻止getValue线程。

如果没有某种线程间的交互,你就无法弄清楚是否有其他线程正在执行remove

实施getValue(...)的正确方法是在地图上进行同步。

我建议删除你自己的锁定,并使用ConcurrentHashMap并将大量工作用于并发性能。

答案 5 :(得分:0)

同步的一个规则是,对于相同的foo,一次只有一个线程可以在synchronized(foo)块中。这是synchronized唯一规则。

嗯,有一些关于内存障碍等的复杂内容,并且单个线程可以同时存在于同一synchronized(foo)的几个嵌套foo块中:

void thing() {
  synchronized(foo) {
    stuff(); // this works fine!
  }
}
void stuff() {
  synchronized(foo) {
    doMoreStuff();
  }
}

...但上述规则基本上是理解synchronized的关键。