2012-07-09 89 views
0

我正在寻找关于同步块的说明。考虑这个类 -Java - 同步对象/块

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方法的同步块中时,我认为它会获取地图对象上的一个锁。这是否意味着尝试通过getValue方法访问地图的其他线程将被阻止? (我希望他们)
  2. 当同步的remove方法中没有线程时,线程将像往常一样访问getValue方法函数,即不会互相阻塞? (我也喜欢)。

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

+0

只有同步的块才会阻塞。 – 2012-07-09 18:47:19

回答

0

synchronized的一个规则是,对于同一个foo,一次只能有一个线程在synchronized(foo)块中。这就是只有规则​​。

嗯,有关于记忆障碍等的一些复杂的东西,和线程可以同时在几个嵌套synchronized(foo)块相同foo

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

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

4

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

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

当remove方法的同步块中没有线程时,将像往常一样访问getValue方法函数的线程即不相互阻塞? (我也喜欢)。

他们不会互相阻止,不会。再次,您需要确保您使用的任何Map实现都可以,尽管可能比写作的同时读取还好。

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

如果你不能使用,我建议你在同步两个getValueremove - 和测量性能。获取无锁的锁相当便宜 - 你真的需要去锁无? (使用ConcurrentHashMap为避免这个问题,当然是一个相当简单的方式,但你应该总是考虑额外的复杂性是需要启动微优化之前,实现您所需要的性能。)

+0

感谢您的快速回答。所以,当你说同步(对象)时,是否意味着如果两个线程到达该代码块,必须彼此等待以使用同步对象?那只是该方法中的线程会阻塞彼此以访问该对象?谢谢! – septerr 2012-07-09 18:50:36

+0

@septerr:不,不仅仅是该方法中的线程 - 任何试图在该对象监视器上同步的线程。基本上,想象每个物体都附带一个挂锁。没有*自动*锁定挂锁,但只要一个线程可以锁定它,无论它被要求锁定它。 – 2012-07-09 18:53:19

+1

'synchronized'的一个规则是,对于同一个'foo',一次只能有一个线程在'synchronized(foo)'块中。这是'synchronized'的_only_规则。 – 2012-07-09 18:53:31

1

你不显示Map实例如何实例化,但假设它不是线程安全的集合实例,则此代码为而不是线程安全。

+0

这是一个普通的HashMap。感谢你的回答。我试图在不影响性能的情况下使其线程安全。 remove方法将很少被调用,而getValue会被调用很多。我将阅读ConcurrentMap。 – septerr 2012-07-09 18:53:50

0

1。getValue()不同步,当一个线程获得一个对象的锁定时,它可以控制所有同步块...不是非同步块。 所以其他线程可以访问getValue()如线程处于sychronized(图)块

2.使用哈希表,这是一个sychronized MAP

0

您有

一个鸡和蛋的问题,我想的getValue线程只有当有线程执行时才阻塞删除操作。

没有某种线程间交互,你不能确定是否有其他线程执行remove

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

我建议您放弃自己的锁定,并使用ConcurrentHashMap并将大量工作用于并发性能。