【问题标题】:Does a call to a threadsafe function need to be syncronized too?对线程安全函数的调用是否需要同步?
【发布时间】:2008-11-19 10:53:36
【问题描述】:
如果我使用 ConcurrentHashMap(其中 put 是线程安全的),并且我提供了一个使用 ConcurrentHashMap put 的公共函数 myPut - 我需要同步我的函数吗?
意思:应该同步吗?
ConcurrentHashMap map;
public void myPut(int something) {
this.map.put(something);
}
【问题讨论】:
标签:
java
synchronization
concurrenthashmap
【解决方案1】:
因为map 引用未声明final,所以它可能会被更改。因此,这里存在潜在的线程错误。
如果map 应该是一个可变引用,那么您将需要做更多的工作。否则使用final。事实上,尽可能使用final,即使它“更容易”不使用。 “final 是新的 [旧] private。”您可能也想制作 map private 和泛型。
【解决方案2】:
ConcurrentHashMap 等并发实用程序的设计使您无需同步:它们将在内部处理线程安全访问。
Tom 说的是真的,您需要考虑地图参考的变化潜力。如果引用实际上没有改变,那么实际上你会在这里摆脱它:ConcurrentHashMap 的内部同步——实际上是 java.util.concurrentlibrary——保证对象放入地图中会安全地发布到其他线程。但我同意即便如此,最好还是决定引用是否可以更改,然后在代码中明确说明这一点(如果不能,则为“最终”;如果可以,则为“易失性”或 AtomicReference可以)。
【解决方案3】:
如果您使用 ConcurrentHashMap,则不应同步“put”,但这并不意味着您的“puts”将被调用一次。这取决于您 Map 的并发级别...
所以你必须知道你想要什么。
顺便看看 ConcurrentHashTable Javadoc,一切都很好解释...
-帕特里克
【解决方案4】:
视情况而定。
当您为要从多个线程使用的对象编写类时,整个游戏都会发生变化。如果您希望提供任何线程安全保证,您需要了解您想要达到的结果。
在这种情况下,如果这是你的类中唯一的方法,那么同步访问这个方法是没有意义的。但它不会是唯一的方法 - 因为它会使课程变得毫无意义。
仅当出于其他原因需要同步此方法以使类线程安全时,您才需要同步此方法 - 此时,您可能想质疑 ConcurrentHashMap 的开销是否值得。
【解决方案5】:
没有。
您可以一次调用 myPut 多次。
put 将一次调用一个,因为 HashTable 的访问需要一次一个。 (另见共享内存中的并发写入)