4

Collections.synchronizedMap() 和所有方法同步的 HashMap 的包装器之间有什么区别。我没有看到任何区别,因为 Collections.synchronizedMap() 在内部为所有方法维护相同的锁。

基本上,以下代码片段有什么区别

Class C {    
    Object o;

    public void foo() {
       synchronized(o) {
           // thread safe code here
       }
    }
}

Class C {
    Object o;

    public synchronized void foo() {

    }
}
4

6 回答 6

3

只有一个区别:

Collections.synchronizedMap能够使用与其自身不同的监视器。

使用同步方法与使用sychnchonized(this)-blocks 相同,这意味着包装器将是监视器,并且可以从包装器外部锁定。

如果您不希望外部应用程序锁定您的显示器,则需要将其隐藏。

另一方面,如果你想以线程安全的方式调用多个方法,这是锁定整个集合的最简单方法(但它确实不是很可扩展)。

Ps:为了重用,最好将方法调用委托给备份映射而不是覆盖类,因为您可以稍后切换到另一个 Map 实现,而无需更改包装器。

于 2010-02-11T16:12:33.353 回答
2

两种方法都在对象上获取一个监视器,因此应该完全相同。差异的主要原因是架构。同步包装器允许轻松扩展基本的非线程安全变体。

话虽如此,不要使用任何一个,使用 ConcurrentHashMap。它使用锁条带化,因此使用起来比任何一种方法都快得多(因为它们在开销+争用方面是相同的)。锁定条带化允许独立锁定支持数组的段。这意味着两个线程请求获取相同锁的可能性较小。

于 2010-02-11T16:58:16.533 回答
1

不要重新发明轮子并使用 API 提供的内容。

于 2010-02-11T16:32:14.930 回答
0

If thread safety is the case, use concurrency package data structures. Using the wrapper class will reduce all accesses to the Map into a sequential queue.

a) Threads waiting to do operations at totally different points in the Map will be waiting for the same lock. Based on the number of threads this can affect the application performance.

b) Consider compound operations on the Map. Using a wrapper with a Single lock will not help. For example. "Look if present then add" kind of operations. Thread syncronization will again become an issue.

于 2012-02-15T18:56:14.423 回答
0

那么,你为什么要问?:) 你真的相信如果将类放在 java.util 包中,那么会发生一些神奇的事情,并且它的 java 代码会以某种棘手的方式工作吗?

它实际上只是用 synchronized {} 块包装了所有方法,仅此而已。

UPD:不同之处在于,如果您使用同步收集而不是自己执行所有同步操作,那么您犯错的机会就会少得多。

UPD 2:正如您在来源中看到的那样,他们使用“互斥”对象作为监视器。当您在方法签名(即synchronized void doSmth())中使用同步修饰符时,对象的当前实例(即this)用作监视器。下面的两个代码块是相同的:

1.

synchronized public void doSmth () {
   someLogic ();
   moreLogic ();
}

synchronized public static void doSmthStatic () {
   someStaticLogic ();
   moreStaticLogic ();
}

2.

public void doSmth () {
   synchronized (this) {
      someLogic ();
      moreLogic ();
   }
}

public static void doSmthStatic () {
   synchronized (ClassName.class) {
      someStaticLogic ();
      moreStaticLogic ();
   }
}
于 2010-02-11T15:19:25.783 回答
0

你应该总是装饰而不是把所有的东西和所有的恐惧都集中到一个大的特色类中。

总是使用普通的 Map 并用 Collections 装饰它,或者使用 java.util.concurrent 并使用真正的锁,这样就可以自动检查和更新地图。明天您可能想将 Hashtable 更改为 Treemap,如果您坚持使用 hashtable,您将遇到麻烦。

于 2010-02-11T06:13:06.960 回答