扩展课时可重入锁定?

时间:2012-08-16 06:21:34

标签: java concurrency synchronized reentrancy

给出以下示例: enter image description here

这个例子来自“Java Concurrency in Practice”。

有评论:

  

因为Widget和LoggingWidget中的doSomething方法都是同步的,所以每个方法都会在继续之前尝试获取Widget上的锁。

为什么LoggingWidget类中的方法doSomething需要获取Widget上的锁?如果是,synchronized中方法doSomething上的LoggingWidget无用,对吗?

2 个答案:

答案 0 :(得分:2)

  

为什么LoggingWidget类中的doSomething方法需要获取Widget上的锁?

假设您要确保2个线程不能同时运行LoggingWidget#doSomething()(在此示例中,您可能希望确保在print语句和对{{{}的调用之间未修改对象1}}),然后你需要使方法同步。

如果不这样做,线程(T1)可以开始运行super.doSomething()并打印对象,另一个线程(T2)也可以开始运行LoggingWidget#doSomething()(该方法未同步)和再次打印对象,然后T2可以运行LoggingWidget#doSomething()(让我们说)更改对象,然后T1将执行super.doSomething()但对象的状态将与打印的不同,因为T2已经在此期间发生了变化。

防止这种情况的一种方法是使方法同步。

  

因为Widget和LoggingWidget中的doSomething方法都是同步的,所以每个方法都会在继续之前尝试获取Widget上的锁。

可重入意味着给定的线程可以重新获取它已经拥有的锁。在这种情况下,当线程进入super.doSomething()时,它会获取LoggingWidget#doSomething(),因为该方法是同步的。当它运行this时,它需要重新获取相同的锁。内在锁不是可重入的,线程会永远阻塞它,试图获取它已经存在的锁并且它不会释放=死锁。

答案 1 :(得分:0)

重入锁定将通过重新获取已锁定的对象的锁定来避免重复。现在,重要的是释放锁定不会释放所有锁定。 JVM内部维护计数器,每次在对象上获取锁定时计数器将递增,并在每次锁定释放时递减。因此,这种机制不仅可以避免死锁,还可以通过保持计数来保持正确性。