在同步块中使用Vector会有什么不同吗?

时间:2011-08-11 13:16:00

标签: java vector synchronization

我在接受采访时被问到这个问题。

  

Vector已经同步。打电话给它会有什么不同吗?      在同步块内?

       synchronized{
            // Call the vector here
       }

我的回答是,除了一些性能损失外,没有任何区别。

答案是否正确?

2 个答案:

答案 0 :(得分:12)

不,这不完全正确。 Vector实例本身同步Vector,而同步块实际上在保存Vector的实例上同步。进入同步块的两种方法必须首先获取与this关联的监视器,然后获取与Vector实例关联的监视器。

边缘情况是,如果其中一个线程持有另一个需要的监视器(如果还有其他同步块),则可能会出现死锁。

然而,仅考虑发布的代码部分,首先在this上获取监视器的线程将首先在Vector上执行操作。此外,Vector实例上的操作序列可以由第一线程执行,而不需要第二线程的任何操作交错;如果要在Vector实例上执行原子操作序列,则必须执行此操作,而在普通同步Vector实例上则不是这种情况。要以伪代码表示,如果在执行相同块的两个或多个线程之间发生上下文切换,则下面表示的两种情况中的操作序列将不同:

案例A

synchronized
{
    vector.add(a);
    vector.add(b);
/*
 * a and b are always added to the vector in sequence.
 * If two threads execute this block, the vector will contain {a,b,a,b}.
 */
}

案例B

{
    vector.add(a);
    vector.add(b);

 /*
  * a and b need not be added to the vector in sequence.
  * If two threads execute this block, the vector will contain one of {a,b,a,b}, {a,a,b,b}....
  */
}

答案 1 :(得分:2)

我会说你的答案是不正确的。 Vector同步的事实仅保护Vector的内部状态。但大多数情况下,您需要使您的类线程安全。

假设您要实现一个最多包含10个元素的容器,并使用Vector来存储这些元素。 add方法如下所示:

public void add(Object item) {
    if (vector.size() == 10) {
        throw new TooManyItemsException();
    }
    else {
        vector.add(10);
    }
}

但是这个方法不是线程安全的,你必须让它同步才能使它成为线程安全的。所以是的,在同步块中调用vector方法确实有所作为。

矢量也可以是更大字段集的一部分,必须以同步方式更新。在这种情况下,即使synchronized块仅从向量中调用方法,它也会保护对象的所有状态。

如果你想要一个完全技术性的答案:它确实有所作为,因为synchronized块和向量调用不会在同一个对象上同步,因此不会做同样的事情。