如果我使用 ConcurrentHashMap(其中 put 是线程安全的),并且我提供了一个使用 ConcurrentHashMap put 的公共函数 myPut - 我需要同步我的函数吗?
含义:这应该同步吗?
ConcurrentHashMap map;
public void myPut(int something) {
this.map.put(something);
}
如果我使用 ConcurrentHashMap(其中 put 是线程安全的),并且我提供了一个使用 ConcurrentHashMap put 的公共函数 myPut - 我需要同步我的函数吗?
含义:这应该同步吗?
ConcurrentHashMap map;
public void myPut(int something) {
this.map.put(something);
}
因为map
没有声明引用,final
所以它可能会被更改。因此,这里有一个潜在的线程错误。
如果map
应该是可变引用,那么您将需要做更多的工作。否则使用final
. 事实上,final
尽可能使用,即使它“更容易”不使用。“final
是新的[旧] private
。” 您可能也想制作map
private
和通用。
ConcurrentHashMap 等并发实用程序的设计使您无需同步:它们将在内部处理线程安全访问。
汤姆说的是真的,你需要考虑地图参考改变的潜力。如果引用实际上没有改变,那么实际上你会在这里逃脱:ConcurrentHashMap 的内部同步——实际上是一般的 java.util.concurrentlibrary——保证放入映射中的对象被安全地发布到其他线程。但我同意即便如此,最好还是决定引用是否可以更改,然后在代码中明确说明这一点(如果不能,则为“final”;如果可以,则为“volatile”或 AtomicReference能够)。
如果您使用 ConcurrentHashMap,则不应同步“put”,但这并不意味着您的“puts”将被调用一次。这取决于您 Map 的并发级别...
所以你必须知道你想要什么。
顺便说一句,看看 ConcurrentHashTable Javadoc,一切都很好解释......
-帕特里克
不
,您可以一次调用 myPut 多次。
put 将一次调用一个,因为 HashTable 的访问需要一次一个。(另见共享内存中的并发写入)
这取决于。
当您为将在多个线程中使用的对象编写类时,整个游戏都会发生变化。如果您希望提供任何线程安全保证,您需要了解您想要达到的结果。
在这种情况下,如果这是您的类中唯一的方法,那么同步对该方法的访问是没有意义的。但它不会是唯一的方法——因为它会使课程变得毫无意义。
如果出于其他原因需要同步此方法以使类线程安全,则只需要同步此方法 - 此时,您可能想质疑 a 的开销是否ConcurrentHashMap
值得。