为什么以下 Vector 代码完全损坏?

Why is the following Vector code broken exactly?

来自: Synchronization in Vectors in Java

考虑到同步,为什么下面的代码是错误的? 向量class在它自己的对象(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 至少将 vector 标记为已弃用?

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

我们只想将 anElement 添加到 vector 中,前提是它是空的。但是使用当前代码可能

            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        |

如您所见,单个操作是线程安全的,但整个事务不是。

Is the vector class not synchronized on its own object (this)?

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

这里我们有两个操作:

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

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

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