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()替换,但我可以看到其他情况,其中对象的同步可能是有用的.
这些类是否需要在此上进行同步以实现其线程安全行为.
不,而且,不仅如此,如果您尝试使用对象锁定,各种代码检查工具将发出警告.
在上面的put方法的情况下,请注意javadoc:
一个哈希表,支持检索的完全并发性和可更新的预期并发性.该类遵循与Hashtable相同的功能规范,并包括与Hashtable的每个方法相对应的方法版本.但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表.在依赖于线程安全但不依赖于其同步细节的程序中,此类可与Hashtable完全互操作.
这意味着选项是线程安全的,并且没有办法做你上面尝试做的事情(锁定整个表).此外,对于您使用的操作(put和get),它们都不需要这样的锁定.
我特别喜欢来自values()方法的javadoc引用:
视图的迭代器是一个"弱一致"的迭代器,它永远不会抛出ConcurrentModificationException,并保证遍历构造迭代器时存在的元素,并且可能(但不保证)反映构造之后的任何修改.
因此,如果您使用此方法,您将获得一个合理的列表:它将具有截止请求时间的数据,可能会或可能不会有任何更新的更新.您不必担心ConcurrentModificationExceptions的保证是一个巨大的问题:您可以编写简单的代码而不需要上面显示的synchronized块,并且知道事情会正常工作.
| 归档时间: |
|
| 查看次数: |
196 次 |
| 最近记录: |