我在接受采访时被问到这个问题。
Vector已经同步。打电话给它会有什么不同吗? 在同步块内?
synchronized{ // Call the vector here }
我的回答是,除了一些性能损失外,没有任何区别。
答案是否正确?
答案 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块和向量调用不会在同一个对象上同步,因此不会做同样的事情。