当一个锁持有一个非最终对象时,该对象的引用是否仍然可以被另一个线程更改?

Mar*_*cus 2 java multithreading final locking synchronized

当一个对象需要同步时,IDE会抱怨它是否设置为非final(因为它的引用不是持久的):

private static Object myTable;
....

synchronized(myTable){          //IDE complains!
     //access myTable here...
}
Run Code Online (Sandbox Code Playgroud)

众所周知,如果持有锁的线程改变了非最终对象的引用,IDE会抱怨阻止另一个线程进入受保护的块.

但是同步对象的引用是否也可以由另一个线程B更改,而线程A保持同一对象的锁定?

Jon*_*eet 5

但是同步对象的引用是否也可以由另一个线程B更改,而线程A保持同一对象的锁定?

如果你的意思是"另一个线程可以改变myTable变量的值,答案就是"绝对"......假设有一个允许的代码路径.它是一个私有变量,所以你应该能够找到所有可以的代码改变价值.

持有一个锁只会阻止另一个线程获取同一个锁.它对哪些代码本身可以访问哪些变量没有任何影响.

作为旁注,区分对象,变量变量的值(它是一个引用,而不是一个对象)很重要.所以没有"最终对象"这样的东西 - 只有变量(以及类和方法)可以是最终的.同样地,没有"同步对象"这样的东西,你不能改变"对象的引用" - 你可以改变变量的值,使它成为对不同对象的引用.在思考这里发生的事情时,在脑海中明确区分这些区别可能会有所帮助.

  • @Marcus:这至少更好,但是一个锁没有一个对象 - 它是一个与一个对象关联的锁(或监视器),它是一个持有锁的线程.它更多"当一个线程持有一个对象的锁定时,该对象的引用是通过一个非最终变量获得的,变量的值是否仍然可以被另一个线程改变?" 但我可能不会用它作为标题:) (2认同)