我有一些代码如下:
class MyClass {
private Set<Integer> set = new HashSet<>();
public void checkAndAddToSet(Integer i) {
if (!set.contains(i)) {
set.add(i);
}
public void checkAndRemove(Integer i) {
if (set.contains(i)) {
set.remove(i);
}
}
}
我需要代码是线程安全的,所以我有两个选择,我可以synchronize
这个类的当前实例,即 synchronized(this)
或我可以在Set
实例上同步,即 synchronized(set)
.
这里哪个更好?我倾向于在数据结构对象set
上同步,但这只是因为将来我可能需要在类中进行进一步的同步,但使用不同的对象锁。
只要您不打算在其他地方的另一个代码中选择此锁,选择哪个显示器锁并不重要。
即使我必须在两者之间做出选择,我也宁愿synchronized(this)
而不是synchronized(set)
。这样做的原因是因为我需要检查 Hashset 代码,它是否在内部使用任何synchronizied(this)
进行任何同步。因此,我可以安全地将synchronized(this)
和平地用于我的代码。
如果您有其他不依赖于该 Set 实例的同步方法,则可以使用 synchronized(set)
,否则使用 synchronized(this)
没有问题。但我建议完全使用 Collections.syncdSet,如果您也有其他同步方法,则完全独立。
喜欢
Set<Integer> set = new HashSet<>();
Set safeSet = Collections.synchronizedSet(set);
这取决于。
当您说synchronize(this)
或将synchronize
关键字添加到方法声明中时 - 它实际上在用于调用此方法的MyClass
实例上同步。
但是,如果您在手动编码的Set
实例上进行同步 - 它将获取与此实例关联的监视器并将其用于同步。
就您的代码而言,您应该对这两种方法都感到满意,而如果您计划将MyClass
用作实用程序类 - 执行putIfAbsent
功能,那么您应该在Set
实例上同步。