我应该在当前对象实例上同步还是在数据结构实例上同步



我有一些代码如下:

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实例上同步。

最新更新