【问题标题】:Why is the following Vector code broken exactly?为什么下面的向量代码完全被破坏了?
【发布时间】:2015-05-03 23:11:50
【问题描述】:

来自: Synchronization in Vectors in Java

为什么考虑到同步,下面的代码会被破坏? 向量类是否未在其自身对象上同步 (this)?

  // BROKEN CODE, needs external synchronization
 // only add an element if the vector is empty
     if(vector.isEmpty())
         vector.add(anElement);

更新:

按照下面的答案(来自 jon Skeet 和 Pshemo),它不会使向量实际上无用吗(我们有 arraylist)?

因为无论如何我们都需要手动同步以用于任何实际用途。 如果是,是什么阻止 Java 将向量标记为至少已弃用?

【问题讨论】:

  • @fge : 知识永远不会伤害 :P
  • 关于您的更新:如果我没记错的话,单个操作的同步可以使我们免于例如由种族引起的不一致状态。当我们调用add(foo)add(bar) 时使用同步,当我们尝试放置一个元素而向量使用的内部数组需要调整大小以存储更多元素时,我们确信这两种方法都将正确执行,而不必担心可能出现的问题并且新元素将被放置在旧数组中,例如在它被存储所有元素的新数组替换之前。
  • 是的,Vector 实际上没用。也就是说,我的理解是 Java 不会弃用那些不打算删除的东西,而且太多的遗留代码依赖于 Vector 来删除它。

标签: java synchronization


【解决方案1】:

向量类在自己的对象(this)上没有同步吗?

是的,但仅限于每个单独的操作。

这里我们有两个操作:

if (vector.isEmpty())
    vector.add(anElement);

有可能在检查isemptyadd 调用之间,不同的线程可以添加一个项目。解决方法是在 combined 操作上添加同步:

synchronized (vector) {
    if (vector.isEmpty()) {
        vector.add(anElement);
    }
}

【讨论】:

    【解决方案2】:

    vector 的状态可以在if(vector.isEmpty()) 测试和vector.add(anElement); 方法之间变化。其他线程可以简单地在这些动作之间添加一些元素。

    我们只想将anElement 添加到向量中,前提是它为空。但是对于当前的代码,有可能

                Thread A       |            Thread B
    ---------------------------+---------------------------
    take vector lock           |
    check if vector is empty   |
    release vector lock        |
                               | take vector lock
                               | add `otherElement`
                               | release vector lock
    take vector lock           |
    add `anElement`            |
    release vector lock        |
    

    所以你看到单个操作是线程安全的,但整个事务不是。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 2020-01-08
      • 2022-07-05
      • 1970-01-01
      • 1970-01-01
      • 2015-01-25
      • 1970-01-01
      相关资源
      最近更新 更多