JDK提供的并发类是否需要使用其实例自己的内部锁来进行同步?

Ale*_*min 3 java concurrency

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

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

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

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

ConcurrentMap<Integer, Account> accounts 
    = new ConcurrentHashMap<Integer, Account>();
Run Code Online (Sandbox Code Playgroud)

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

而在另一个线程

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

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

Bob*_*oss 6

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

不,而且,不仅如此,如果您尝试使用对象锁定,各种代码检查工具将发出警告.

在上面的put方法的情况下,请注意javadoc:

一个哈希表,支持检索的完全并发性和可更新的预期并发性.该类遵循与Hashtable相同的功能规范,并包括与Hashtable的每个方法相对应的方法版本.但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表.在依赖于线程安全但不依赖于其同步细节的程序中,此类可与Hashtable完全互操作.

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

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

视图的迭代器是一个"弱一致"的迭代器,它永远不会抛出ConcurrentModificationException,并保证遍历构造迭代器时存在的元素,并且可能(但不保证)反映构造之后的任何修改.

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