我正在寻找有关同步块的说明。考虑这个类 -
public class A{
Map map;
public getValue(String key){
return map.get(key);
}
public remove(String key){
synchronized(map){
map.remove(key);
}
}
}
A是单身人士。多个线程在整个应用程序中大量访问getValue。我正在添加一个新方法,删除,从地图中删除一个键。如果删除如上所述,
我希望只有在执行删除操作的线程时才阻止getValue线程。
答案 0 :(得分:4)
当一个线程在remove方法的synchronized块中时,我认为它将在map对象上获得一个锁。这是否意味着其他线程试图通过getValue方法访问地图将被阻止?
没有。这意味着你遇到了问题,除非你碰巧使用线程安全的地图实现。
如果remove方法的synchronized方块中没有线程,那么访问getValue方法的线程是否会照常运行,即不会相互阻塞? (我也喜欢这样)。
他们不会互相阻挠,不。同样,你需要确保使用你正在使用的Map
实现是可以的,尽管它可能可能比在写作的同时阅读更好。
您应该考虑使用ConcurrentMap
实施(例如ConcurrentHashMap
),此时您根本不需要任何同步。
如果你不能使用它,我建议在同步 getValue
和remove
- 以及测量性能。获得无竞争锁定相当便宜 - 你真的需要无锁吗? (当然,使用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
的关键。