使非同步数据结构线程安全的方法

5
我想知道是否存在其他非同步数据结构的线程安全方法,而不是使用像Hashtable和Vector这样的同步数据结构,或者使用像Collections.synchronizedList(List arg)或Collections.synchronizedMap(Map arg)这样的包装器? 在采访中我被问到如何使哈希表线程安全,我告诉他使用Hashtable或ConcurrentHashMap或使用Collections.synchronizedMap封装器,但似乎这些答案并不是他要找的。

这取决于数据结构。你能更具体一些吗? - Dmitry B.
是的,我稍微更新了我的问题。 - peter
或者使用ConcurrentHashMap,它使用CAS原语而不是锁。 - Chander Shivdasani
我实际上说的是ConcurrentHashMap和CopyonWriteArrayList,而不是hashtable和vector。 - peter
除了在每个操作上锁定整个数据结构或将其设置为只读,没有通用的方法可以使任意数据结构不可变。 - Louis Wasserman
2个回答

4

是的,你可以使其不可变。在许多情况下,这实际上是使代码线程安全的绝佳方式。


你能举个例子吗?比如说你想让哈希表变成线程安全的。 - peter
基本上你所需要做的就是不要暴露任何改变 Map 状态的方法,并确保每次对 Map 的更改都会创建一个新的 Map。虽然这种方法并非适用于所有情况,但能够应用时它可以为你节省大量麻烦。 - Keppil
1
许多库都有专门的不可变集合版本,例如Guava的ImmutableMap - Louis Wasserman
实用类java.util.Collections有一些方法可以将各种集合类转换为不可变集合。请查看unmodifiable*()方法。 - Ted Hopp
1
@user1389813:当需要更改时,您将需要创建一个全新的“Map”,因此这将需要进行深层复制以确保绝对安全。 - Keppil
显示剩余3条评论

2
是的。如果您自己同步构造,则可以这样做。但出于明显的原因,不建议这样做...

1
为什么不推荐使用 Vector?引入 ArrayList 作为 Vector 的替代品的主要原因之一是,应用程序实际上需要同步的级别通常比对 Vector 实例进行的单个函数调用更高。这通常是通过使用 synchronized 块或使用锁对象(来自 java.util.concurrent.locs)来完成的。 - Ted Hopp
是的,我说过它可以做到。我的意思是最好使用其中一个“synchronized”版本,而不是尝试自己进行同步。 - Cratylus
不一定。如果您想要将大量操作同步在一起,使用synchronized包装器是无法帮助您的。 - Louis Wasserman
另一个例子是:如果(!map.containsKey(key)),则map.put(key, value)。 - Chander Shivdasani
如果你能使用ConcurrentHashMap,那么是的。但一般来说,如果你想锁定整个操作组,你可能需要自己进行同步。 - Louis Wasserman
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接