您的位置:首页 > 运维架构 > 网站架构

架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock

2017-01-04 09:23 375 查看
ReentrantLock

有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级。

this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决方案,后面jdk干脆就提供了一个Lock类。

伪代码:

Lock lock = new ReentrantLock();//新建一个lock

Condition condition = lock.newCondition();//获取条件

method1(){

  try{

    lock.lock();

    代码块;

    lock.unlock();

    后续代码块;

  }

}

method2(){

  try{

    lock.lock();

    代码块;

    lock.signal();

  }

}

单condition操作:

1 import java.util.concurrent.locks.Condition;
2 import java.util.concurrent.locks.Lock;
3 import java.util.concurrent.locks.ReentrantLock;
4
5 public class UseCondition {
6
7     private Lock lock = new ReentrantLock();
8     private Condition condition = lock.newCondition();
9
10     public void method1(){
11         try {
12             lock.lock();
13             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
14             Thread.sleep(3000);
15             System.out.println("当前线程:" + Thread.currentThread().getName() + "释放锁..");
16             condition.await();    // Object wait
17             System.out.println("当前线程:" + Thread.currentThread().getName() +"继续执行...");
18         } catch (Exception e) {
19             e.printStackTrace();
20         } finally {
21             lock.unlock();
22         }
23     }
24
25     public void method2(){
26         try {
27             lock.lock();
28             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
29             Thread.sleep(3000);
30             System.out.println("当前线程:" + Thread.currentThread().getName() + "发出唤醒..");
31             condition.signal();        //Object notify
32         } catch (Exception e) {
33             e.printStackTrace();
34         } finally {
35             lock.unlock();
36         }
37     }
38
39     public static void main(String[] args) {
40
41         final UseCondition uc = new UseCondition();
42         Thread t1 = new Thread(new Runnable() {
43             @Override
44             public void run() {
45                 uc.method1();
46             }
47         }, "t1");
48         Thread t2 = new Thread(new Runnable() {
49             @Override
50             public void run() {
51                 uc.method2();
52             }
53         }, "t2");
54         t1.start();
55
56         t2.start();
57     }
58
59
60
61 }


执行结果:



解释:线程1调用method1方法,线程2调用同一对象的method2方法,线程1先启动,线程1获取锁,进入method1的代码块,线程2也启动了,单是线程2被锁定,直到线程1发出lock.unlock()了,线程1才将锁释放,这时线程2获取锁,执行method2的代码块,线程2发出lock.signal(); 线程1才继续执行后续代码块。

多condition操作:

1 import java.util.concurrent.locks.Condition;
2 import java.util.concurrent.locks.ReentrantLock;
3
4 public class UseManyCondition {
5
6     private ReentrantLock lock = new ReentrantLock();
7     private Condition c1 = lock.newCondition();
8     private Condition c2 = lock.newCondition();
9
10     public void m1(){
11         try {
12             lock.lock();
13             System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m1等待..");
14             c1.await();
15             System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m1继续..");
16         } catch (Exception e) {
17             e.printStackTrace();
18         } finally {
19             lock.unlock();
20         }
21     }
22
23     public void m2(){
24         try {
25             lock.lock();
26             System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m2等待..");
27             c1.await();
28             System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m2继续..");
29         } catch (Exception e) {
30             e.printStackTrace();
31         } finally {
32             lock.unlock();
33         }
34     }
35
36     public void m3(){
37         try {
38             lock.lock();
39             System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m3等待..");
40             c2.await();
41             System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m3继续..");
42         } catch (Exception e) {
43             e.printStackTrace();
44         } finally {
45             lock.unlock();
46         }
47     }
48
49     public void m4(){
50         try {
51             lock.lock();
52             System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
53             c1.signalAll();
54         } catch (Exception e) {
55             e.printStackTrace();
56         } finally {
57             lock.unlock();
58         }
59     }
60
61     public void m5(){
62         try {
63             lock.lock();
64             System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
65             c2.signal();
66         } catch (Exception e) {
67             e.printStackTrace();
68         } finally {
69             lock.unlock();
70         }
71     }
72
73     public static void main(String[] args) {
74
75
76         final UseManyCondition umc = new UseManyCondition();
77         Thread t1 = new Thread(new Runnable() {
78             @Override
79             public void run() {
80                 umc.m1();
81             }
82         },"t1");
83         Thread t2 = new Thread(new Runnable() {
84             @Override
85             public void run() {
86                 umc.m2();
87             }
88         },"t2");
89         Thread t3 = new Thread(new Runnable() {
90             @Override
91             public void run() {
92                 umc.m3();
93             }
94         },"t3");
95         Thread t4 = new Thread(new Runnable() {
96             @Override
97             public void run() {
98                 umc.m4();
99             }
100         },"t4");
101         Thread t5 = new Thread(new Runnable() {
102             @Override
103             public void run() {
104                 umc.m5();
105             }
106         },"t5");
107
108         t1.start();    // c1
109         t2.start();    // c1
110         t3.start();    // c2
111
112
113         try {
114             Thread.sleep(2000);
115         } catch (InterruptedException e) {
116             e.printStackTrace();
117         }
118
119         t4.start();    // c1
120         try {
121             Thread.sleep(2000);
122         } catch (InterruptedException e) {
123             e.printStackTrace();
124         }
125         t5.start();    // c2
126
127     }
128
129
130
131 }


执行结果:



解释:t1、t2线程都是用第一个condition c1,t3线程用第二个condition c2,t4线程发出c1.signalAll() 唤醒t1和t2线程,t5发出c2.signal()唤醒t3线程。

ReentrantReadWriteLock

读写分离锁,读读共享、写写互斥、读写互斥。

1 import java.util.concurrent.locks.ReentrantReadWriteLock;
2 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
3 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
4
5 public class UseReentrantReadWriteLock {
6
7     private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
8     private ReadLock readLock = rwLock.readLock();
9     private WriteLock writeLock = rwLock.writeLock();
10
11     public void read(){
12         try {
13             readLock.lock();
14             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
15             Thread.sleep(3000);
16             System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
17         } catch (Exception e) {
18             e.printStackTrace();
19         } finally {
20             readLock.unlock();
21         }
22     }
23
24     public void write(){
25         try {
26             writeLock.lock();
27             System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
28             Thread.sleep(3000);
29             System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
30         } catch (Exception e) {
31             e.printStackTrace();
32         } finally {
33             writeLock.unlock();
34         }
35     }
36
37     public static void main(String[] args) {
38
39         final UseReentrantReadWriteLock urrw = new UseReentrantReadWriteLock();
40
41         Thread t1 = new Thread(new Runnable() {
42             @Override
43             public void run() {
44                 urrw.read();
45             }
46         }, "t1");
47         Thread t2 = new Thread(new Runnable() {
48             @Override
49             public void run() {
50                 urrw.read();
51             }
52         }, "t2");
53         Thread t3 = new Thread(new Runnable() {
54             @Override
55             public void run() {
56                 urrw.write();
57             }
58         }, "t3");
59         Thread t4 = new Thread(new Runnable() {
60             @Override
61             public void run() {
62                 urrw.write();
63             }
64         }, "t4");
65
66         t1.start();
67         t2.start();
68
69 //        t1.start(); // R
70 //        t3.start(); // W
71
72 //        t3.start();
73 //        t4.start();
74     }
75 }


解释:t1和t2都是读,是共享的,可同时获得readLock同时进入read方法执行。t1是读和t3是写,是互斥的,只有t1执行完t3才能执行。t3、t4都是写,是互斥的,只有等t3执行完t4才能继续。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: