0

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

public class A{
Map map;

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

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

A 是单例。getValue 在整个应用程序中被多个线程大量访问。我正在添加一个新方法 remove,它从地图中删除一个键。如果按上述方式实现 remove,

  1. 当一个线程在 remove 方法的同步块中时,我假设它会在 map 对象上获得一个锁。这是否意味着尝试通过 getValue 方法访问地图的其他线程将被阻止?(我希望他们这样做。)
  2. 当remove方法的同步块中没有线程时,访问getValue方法的线程是否会正常运行,即不会互相阻塞?(我也想要)。

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

4

6 回答 6

4

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

不,这意味着你遇到了问题,除非你碰巧使用了线程安全的映射实现。

当remove方法的同步块中没有线程时,访问getValue方法的线程是否会像往常一样发挥作用,即不会互相阻塞?(我也想要)。

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

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

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

于 2012-07-09T18:46:11.237 回答
4

如果我正确理解了您的需求,您可以查看ConcurrentMap,当然还有ConcurrentHashMap ,我相信它是随 Java 5.0 引入的,并且支持一定程度的并发性。

于 2012-07-09T18:46:51.597 回答
1

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

于 2012-07-09T18:46:36.623 回答
0

1. getValue() 是不同步的,当一个线程获得一个对象的锁时,它拥有对所有同步块的控制......不是非同步的...... 所以其他线程可以访问 getValue() 当 as线程处于同步(映射)块中

2.使用HashTable,它是一个同步的MAP

于 2012-07-09T18:47:20.773 回答
0

你有鸡和蛋的问题

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

如果没有某种线程间交互,您无法确定是否有其他线程执行remove.

正确的实现方式getValue(...)是在地图上同步。

我建议放弃自己的锁定,并使用 aConcurrentHashMap并利用大量工作来提高并发性能。

于 2012-07-09T18:47:31.787 回答
0

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

嗯,有一些关于内存屏障等复杂的东西,一个线程可以同时在几个嵌套synchronized(foo)块中foo

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

……但上面所说的规则基本上是理解的关键synchronized

于 2012-07-12T09:36:11.337 回答