可重入
指的是同一线程的外层函数获得锁之后,内层函数可以直接再次获取该锁。
怎么理解这段话呢?
举个通俗例子 --- 摇号。在这个故事中把摇到号比喻做线程获取到了锁
。假设我家目前有3辆车,我想给我家3辆车都上牌照。问题是摇到一次号只能给一辆车上号,如果我想给3辆车上牌照,我需要摇3次号。这样的一种行为称作不可重入
。反之,摇到一次号就可以一直上牌照,直到自己主动弃权,这样的一种行为则可称为可重入
。
有什么好处?
- 避免死锁
- 提升封装性(避免一次次的加锁,解锁)
- 粒度:针对
线程
而非调用
(Linux中的phread
的粒度则是针对调用
层面)- 证明同一个方式是可重入的
package synchronize; /** * 描述:可重入粒度测试:递归调用本方法(证明同一个方 * 式是可重入的) */ public class SynchronizedRecursion10 { int a = 0; public static void main(String[] args) { SynchronizedRecursion10 synchronizedRecursion10 = new SynchronizedRecursion10(); synchronizedRecursion10.method1(); } private synchronized void method1() { System.out.println("这是methods方法, a=" + a); if (a == 0){ a++; method1(); } } }
- 证明可重入不要求是同一个方法
package synchronize; /** * 描述:可重入粒度测试:调用类内另外的方法:证明可重入不要求是同一个方法 */ public class SynchronizedOtherMethod11 { public static void main(String[] args) { SynchronizedOtherMethod11 synchronizedOtherMethod11 = new SynchronizedOtherMethod11(); synchronizedOtherMethod11.method1(); } public synchronized void method1() { System.out.println("我是method1"); method2(); } public synchronized void method2() { System.out.println("我是method2"); } }
- 证明可重入不要求是同一个类中的方法
package synchronize; /** * 描述: 可重入粒度测试,调用父类方法 */ public class SynchronizedSuperclass12 { public synchronized void doSomething(){ System.out.println("我是父类方法"); } } class TestClass extends SynchronizedSuperclass12{ public synchronized void doSomething(){ System.out.println("我是子类方法"); super.doSomething(); } public static void main(String[] args) { TestClass s = new TestClass(); s.doSomething(); } }
不可中断
一旦这个锁已经被别人获得了,如果我还想获取,我只能选择等待或者阻塞,直到别的线程释放
这个锁。如果别人永远不释放锁,那么我只能永远的等下去。
相比之下,未来会介绍Lock
类,它可以拥有中断的能力。第一点,如果它觉得我等的时间太长,有权中断现在已经获取到锁的线程的执行;第二点:如果它觉得等待的时间太长了,不想再等了,也可以退出。
网友评论