JDK提供的并发类是否需要使用它们的实例拥有内部锁来进行同步?

时间:2011-05-14 21:37:32

标签: java concurrency

JDK提供了一组线程安全的类,如ConcurrentHashMap,ConcurrentLinkedQueue和AtomicInteger。

这些类是否需要在this上同步以实现其线程安全行为?

如果他们这样做,我们可以对这些对象实现我们自己的同步操作,并将它们与内置对象混合使用?

换句话说,这样做是安全的:

ConcurrentMap<Integer, Account> accounts 
    = new ConcurrentHashMap<Integer, Account>();

// Add an account atomically
synchronized(accounts) {
    if (!accounts.containsKey(id)) {
        Account account = new Account();
        accounts.put(id, account);
    }
}

在另一个帖子中

// Access the object expecting it to synchronize(this){…} internally
accounts.get(id);

请注意,上面的简单同步块可能会被putIfAbsent()替换,但我可以看到其他情况,其中同步对象可能有用。

1 个答案:

答案 0 :(得分:6)

  

这些课程是否需要   同步这个来实现他们的   线程安全的行为。

否,不仅如此,如果您尝试使用对象锁定,各种代码检查工具也会发出警告。

如果是上面的put方法,请注意javadoc

  

支持完整的哈希表   检索和并发   可调节的预期并发性   更新。这门课也服从同样的道理   功能规范为Hashtable,   并包括方法的版本   对应于每种方法   哈希表。但是,尽管如此   操作是线程安全的,检索   操作不需要锁定,并且   没有任何锁定支持   整个表格的方式   阻止所有访问。这堂课是   与Hashtable完全互操作   依赖于其线程的程序   安全但不同步   的信息。

这意味着选项是线程安全的,并且没有办法执行上面尝试的操作(锁定整个表)。此外,对于您使用的操作(put和get),它们都不需要这样的锁定。

我特别喜欢来自values()方法的javadoc引用:

  

视图的迭代器是“弱的   一致的“迭代器永远不会   抛出ConcurrentModificationException,   并保证将元素遍历为   他们建造的时候就存在了   迭代器,可能(但不是   保证反映任何   之后的修改   构造

因此,如果您使用此方法,您将获得一个合理的列表:它将具有截止请求时间的数据,可能会或可能不会有任何更新的更新。保证您不必担心ConcurrentModificationExceptions是一个巨大的问题:您可以编写简单的代码而不使用上面显示的synchronized块,并且知道事情将会起作用。