可重入锁/不可重入锁

原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11395621.html

 

可重入锁

可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提是同一个对象或者类)

Note:

ReentrantLock和synchronized都是可重入锁

 1 public class TestLock {  
 2     public synchronized void test1() throws InterruptedException {  
 3         Thread.sleep(1000);  
 4         System.out.println("test1 invoked...");  
 5         test2();  
 6     }  
 7   
 8     public synchronized void test2() throws InterruptedException {  
 9         Thread.sleep(1000);  
10         System.out.println("test2 invoked...");  
11     }  
12   
13     public static void main(String[] args) throws InterruptedException {  
14         TestLock testLock = new TestLock();  
15         testLock.test1();  
16     }  
17 }

上面的代码就是一个可重入锁的一个特点,如果不是可重入锁的话,test2可能不会被当前线程执行,可能造成死锁。 

 

不可重入锁

不可重入锁,与可重入锁相反,不可递归调用,递归调用就会发生死锁。

使用自旋锁来模拟一个不可重入锁

 1 import java.util.concurrent.atomic.AtomicReference;  
 2   
 3 public class UnreentrantLockTest {  
 4     private static UnreentrantLock lock = new UnreentrantLock();  
 5   
 6     public static void main(String[] args) {  
 7         lock.lock();  
 8   
 9         test();  
10   
11         lock.unlock();  
12     }  
13   
14     private static void test() {  
15         lock.lock();  
16   
17         System.out.println("test invoked...");  
18   
19         lock.unlock();  
20     }  
21   
22     private static class UnreentrantLock {  
23         private AtomicReference<Thread> owner = new AtomicReference<>();  
24   
25         public void lock() {  
26             Thread currentThread = Thread.currentThread();  
27   
28             for (; ; ) {  
29                 System.out.println(owner);  
30                 if (owner.compareAndSet(null, currentThread)) {  
31                     System.out.println(currentThread + " locked...");  
32                     return;  
33                 }  
34             }  
35         }  
36   
37         public void unlock() {  
38             Thread currentThread = Thread.currentThread();  
39   
40             owner.compareAndSet(currentThread, null);  
41   
42             System.out.println(currentThread + " unlock...");  
43         }  
44     }  
45 }  

Note:

使用原子引用来存放线程,同一个线程两次调用lock()方法,如果不执行unlock()释放锁的话,第二次调用自旋的时候就会产生死锁,这个锁是不可重入的

 

修改上述代码,将它改造成可重入锁,在执行每次操作之前,判断当前锁持有者是否是当前对象,采用state计数

 1 import java.util.concurrent.atomic.AtomicReference;  
 2   
 3 public class ReentrantLockTest {  
 4     private static ReentrantLock lock = new ReentrantLock();  
 5   
 6     public static void main(String[] args) {  
 7         lock.lock();  
 8   
 9         test();  
10   
11         lock.unlock();  
12     }  
13   
14     private static void test() {  
15         lock.lock();  
16   
17         System.out.println("test invoked...");  
18   
19         test1();  
20   
21         lock.unlock();  
22     }  
23   
24     private static void test1() {  
25         lock.lock();  
26   
27         System.out.println("test2 invoked...");  
28   
29         lock.unlock();  
30     }  
31   
32     private static class ReentrantLock {  
33         private AtomicReference<Thread> owner = new AtomicReference<>();  
34         private int state = 0;  
35   
36         public void lock() {  
37             Thread currentThread = Thread.currentThread();  
38   
39             if (currentThread == owner.get()) {  
40                 state++;  
41                 return;  
42             }  
43   
44             for (; ; ) {  
45                 System.out.println(owner);  
46                 if (!owner.compareAndSet(null, currentThread)) {  
47                     return;  
48                 }  
49             }  
50         }  
51   
52         public void unlock() {  
53             Thread currentThread = Thread.currentThread();  
54   
55             if (currentThread == owner.get()) {  
56                 if (state != 0) {  
57                     state--;  
58                 } else {  
59                     owner.compareAndSet(currentThread, null);  
60                 }  
61             }  
62         }  
63     }  
64 }  

 

posted @ 2019-08-22 17:24  李白与酒  阅读(902)  评论(0编辑  收藏  举报