获取锁定时重新分配对象变量

时间:2014-02-24 07:28:04

标签: java multithreading synchronized

以下代码是否有意义:

主题A:

synchronized(mObj) {
    return mObj.x;
}

主题B:

synchronized(mObj) {
    mObj = new Object();
}

特别是,是否保证两个同步部分始终互斥?

3 个答案:

答案 0 :(得分:3)

此处未正确实施未同步。

每个对象都有一个锁定,而执行时,你会执行锁定并在完成后释放它,然后下一个线程将会响应谁在等待它。

mObj = new Object();

重新分配新的对象将会产生冲突。

假设情况 - 第一线程T1通过获取锁执行同步部分,并且线程t2正在等待获得由线程T1获取的锁。现在,线程T1用新的mObj重新分配Object对象,并通过释放对象(旧对象)锁定离开同步部分,线程t2现在能够执行锁定并进入同步块。

此时如果线程T3试图执行同步块,“线程T3是否能够获取锁定?”。答案是肯定的。 synchronized(mObj)现在mObj引用引用了一个新对象而没有One获得锁定,因此T3可以执行此操作。所以这是相互矛盾的情况。

答案 1 :(得分:2)

该变量上的锁,只有对象。

这是一个时间表,显示“线程安全”,因为无法保证生成的时间表。

mObj = X       
synchronized(mObj) // B1 -> mObj evaluates to X
   mObj = Y        // B2
   DoSomeWork()    // B3
synchronized(mObj) // A1 -> mObj MAY evaluate to either X or Y
                   //       because the evaluation of the variable is NOT
                   //       within scope of the synchronization. If it
                   //       evaluates to Y then it is NOT synchronized on X.
   return mObj.x   // A2 -> May or may not be mutually exclusive wrt B3
                   //       (That is, neither case is "guaranteed".)

我在“线程B”同步上下文的末尾添加了一个“DoSomeWork”来绘制我的参数,但我认为可以应用相同的逻辑/参数 - 它的“可能是X或Y” - 没有这样的,因此认为两个同步块保证是互斥的。

答案 2 :(得分:0)

对于您的问题“是否保证两个同步部分始终互相排斥” 是的,它将是相互排斥的,但不是人们想要的方式。

场景1:假设Thread1获得了监视器对象并首先进入同步块,然后显然Thread2将等待并重新分配mObj将不会产生任何影响。快乐的场景:)

场景2:线程2获取监视器锁定并首先进入同步块,并且线程1正在等待mObj。现在,当您将mObj重新分配给新对象mObj1时,它将更改监视器对象,这将导致线程1永远等待监视器锁定,因为当Thread2将从同步块中退出时,它将释放监视器对象mObj1而不是mObj的锁定。这就是为什么我说,它仍然是相互排斥的,但不是某人想要的方式:)。

场景3:如果你正在使用wait-notify解决方案,那么你会做同样的事情,它将是灾难性的并导致你illeagalMonitorstate异常的原因与你试图在某个监视器上等待或通知你所做的相同在重新分配对象时,你有锁/同步块。