【问题标题】:Should I synchronize on the current object instance or on the data structure instance?我应该在当前对象实例上同步还是在数据结构实例上同步?
【发布时间】:2016-03-11 13:08:34
【问题描述】:

我有一些代码如下:

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实例上同步,即@987654325 @。

这里哪个是更好的选择?我倾向于在数据结构对象set 上进行同步,但这只是因为将来我可能需要在类中进行进一步的同步,但使用不同的对象锁。

【问题讨论】:

  • 我认为防范set 就足够了。另外,考虑将set 定为最终版本。需要拨打contains()吗? Set 接口的契约(由 HashSet 满足)已经检查并返回布尔值以向调用者传达它所做的事情。
  • 那么,你找到答案了吗?

标签: java multithreading


【解决方案1】:

只要您不打算在别处的另一个代码处选择此锁,您选择哪个监视器锁都没有关系。

即使我必须在两者之间进行选择,我还是更喜欢 synchronized(this) 而不是 synchronized(set)。这样做的原因是因为我需要检查 Hashset 代码是否在内部使用任何 synchronizied(this) 进行任何同步。 所以我可以安全地在我的代码中使用synchronized(this)

【讨论】:

    【解决方案2】:

    如果您有其他不依赖于该 Set 实例的同步方法,您可以使用synchronized(set),否则使用synchronized(this) 没有问题。但我建议完全使用Collections.synchronizedSet,如果您还有其他同步方法,请独立使用。

    喜欢

    Set<Integer> set = new HashSet<>();
    Set safeSet = Collections.synchronizedSet(set);
    

    【讨论】:

    • 使用Collections.synchronizedSet(set) 不会使set 线程对相关操作安全。我们仍然需要客户端锁定来达到同样的效果。
    • @Tirath 我认为只有在对集合使用迭代器时才需要同步...请解释为什么不适用于这个问题
    • 同意同步迭代器。假设我们有safeSet,我们在相关的checkAndAddToSetcheckAndRemove 方法中使用它。这些方法不同步,这是一个问题。假设我们修改为使然后同步。现在,这些方法获取MyClass 实例而不是safeSet 的监视器。我们有两个不同的锁。我认为这证明了我的观点。
    • @Tirath "These methods aren't synchronized and thats a problem."。如果safe.add()remove()Collections.synchronizedSet(set) 给出的包装器同步,这怎么会是一个问题。请解释如何在多线程环境中破坏checkAndAddToSet
    【解决方案3】:

    视情况而定。

    当您说synchronize(this) 或在方法声明中添加synchronize 关键字时,它实际上会在用于调用此方法的MyClass 实例上同步。

    但是,如果您在手动编码的 Set 实例上进行同步 - 它将获取与此实例关联的监视器并将其用于同步。

    就您的代码而言,这两种方法都应该没问题,而如果您打算使用 MyClass 作为实用程序类 - 执行 putIfAbsent 功能,那么您应该在 Set 实例上同步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-05
      • 2017-05-15
      • 1970-01-01
      相关资源
      最近更新 更多