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