Java 在获取对象变量的锁时重新分配对象变量

Java 在获取对象变量的锁时重新分配对象变量,java,multithreading,synchronized,Java,Multithreading,Synchronized,以下代码有意义吗: 线程A: synchronized(mObj) { return mObj.x; } 线程B: synchronized(mObj) { mObj = new Object(); } 特别是,是否保证两个同步的部分始终是互斥的?此处未正确实现“无同步” 每个对象在执行时都有一个锁,并激活锁并在完成后释放锁,然后下一个线程将激活等待该锁的线程 mObj = new Object(); 重新分配新对象将在这方面产生冲突 假设一个场景——第一个线程T1通过获取

以下代码有意义吗:

线程A:

synchronized(mObj) {
    return mObj.x;
}
线程B:

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

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

此处未正确实现“无同步”

每个对象在执行时都有一个锁,并激活锁并在完成后释放锁,然后下一个线程将激活等待该锁的线程

mObj = new Object();
重新分配新对象将在这方面产生冲突

假设一个场景——第一个线程T1通过获取锁来执行同步部分,而线程t2正在等待获取线程T1获取的锁。现在,线程T1用新的
对象重新分配
mObj
对象,并通过释放对象(旧对象)锁离开同步部分,线程t2现在能够激活锁并进入同步块

此时,如果线程T3尝试执行同步化的块,“线程T3是否能够获取锁?”。答案是肯定的
synchronized(mObj)
now
mObj
reference正在引用一个新对象,并且没有人获得锁,因此T3可以这样做。所以这是一种矛盾的情况。

锁不在变量上,只在对象上

下面是一个计划,它表明这不是“线程安全的”,因为生成的计划没有保证

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".)
我在“Thread B”同步上下文的末尾添加了一个“DoSomeWork”来绘制我的参数,但我认为相同的逻辑/参数-它的“可能是X或Y”-可以在没有这样的逻辑/参数的情况下应用,因此认为这两个同步块不能保证相互排斥。

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

场景1:假设Thread1获得了监视器对象并首先进入同步块,那么Thread2显然会等待,重新分配mObj不会有任何效果。快乐场景:)

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


场景3:如果您正在使用等待通知解决方案,然后执行相同的操作,那么这将是灾难性的,并导致您出现IllegalMonitorState异常,原因与您在重新分配obj时尝试在没有锁定/同步块的某个监视器上等待或通知的原因相同。

锁定不在变量上,只有对象。用作锁的变量应声明为
final
,以避免此类错误。您的场景并不是真的有问题。问题在于,如果第一个线程获取锁,进入同步部分,重新分配变量,然后另一个线程能够进入同步部分,即使第一个线程打开e还没有离开它,因为线程现在在两个不同的对象上同步。嗯,不完全是我认为有点复杂的场景。呵呵,你的问题陈述很简短或令人印象深刻。在你介绍最后一段之前,我发表了我的评论。不过,你不需要3个线程来说明问题。