类级同步如何在Java中实现?

时间:2017-01-20 11:00:16

标签: java multithreading thread-safety synchronized

我有一个有某种状态的类的对象。 此对象有两种方法(method1()method2()),两种方法都在更改obj的状态。 method1()已同步,但method2()未同步。

现在两个线程,thread1和threads2接近对象 - > threads1调用同步的method1() - > thread2调用未同步的method2()

我在测试结果中发现的是method2()正在正确执行,即使method1()持有锁定。但我认为如果通过在方法上放置synchronized关键字来获取整个对象的锁定,则可以执行多少其他方法。它应该等待。

非常感谢您的意见。

3 个答案:

答案 0 :(得分:2)

当我们说调用同步方法或块导致锁定时,所有这意味着线程专门获取锁。这并不意味着线程获取的锁定对象的状态会受到任何其他保护。

(内部锁附加到对象,包括类对象,这是语言设计者的方便。这个决定可能不是最好的。使用专用对象来锁定通常是一个更好的主意。)

您的未同步调用可能会破坏共享状态。除此之外,没有内存屏障,并且调用未同步方法的线程所做的更改可能不被其他线程看到。在进行重新排序代码等优化时,JIT不会考虑跨线程可见性问题。

可能很难预测未充分同步的代码会发生什么。

答案 1 :(得分:1)

  

但是我认为如果通过在方法上放置同步来获取整个对象的锁,那么就可以执行任何其他方法。它应该等待。

锁不知道它锁定了什么。它只是阻止其他线程获取同一个锁。

答案 2 :(得分:1)

这里有一些很好的答案,但我认为还有更多的细节。

  

我的测试结果发现,即使method1()有一个锁,方法2()也很乐意执行。

当线程进入synchronized方法时,它会锁定与对象实例关联的监视器。其他线程可以根据需要在同一个对象实例上调用其他非同步方法。由thread1持有的锁定不会以任何方式更改obj。只有当thread2 锁定相同的对象实例时才会被阻止。

  

但是我认为如果通过在方法上放置同步来获取整个对象的锁,那么就可以执行任何其他方法。它应该等待。

不,事实并非如此。如果每个方法调用都必须查看对象的方法是否被锁定,那么会有很大的性能损失。