ReentrantReadWriteLock读写锁的使用
Lock比傳統(tǒng)線程模型中的synchronized方式更加面向?qū)ο?#xff0c;與生活中的鎖類似,鎖本身也應(yīng)該是一個對象。兩個線程執(zhí)行的代碼片段要實現(xiàn)同步互斥的效果,它們必須用同一個Lock對象。
讀寫鎖:分為讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,這是由jvm自己控制的,你只要上好相應(yīng)的鎖即可。如果你的代碼只讀數(shù)據(jù),可以很多人同時讀,但不能同時寫,那就上讀鎖;如果你的代碼修改數(shù)據(jù),只能有一個人在寫,且不能同時讀取,那就上寫鎖。總之,讀的時候上讀鎖,寫的時候上寫鎖!
ReentrantReadWriteLock會使用兩把鎖來解決問題,一個讀鎖,一個寫鎖
線程進(jìn)入讀鎖的前提條件:
??? 沒有其他線程的寫鎖,
??? 沒有寫請求或者有寫請求,但調(diào)用線程和持有鎖的線程是同一個
線程進(jìn)入寫鎖的前提條件:
??? 沒有其他線程的讀鎖
??? 沒有其他線程的寫鎖
到ReentrantReadWriteLock,首先要做的是與ReentrantLock劃清界限。它和后者都是單獨的實現(xiàn),彼此之間沒有繼承或?qū)崿F(xiàn)的關(guān)系。然后就是總結(jié)這個鎖機制的特性了:?
? ? ?(a).重入方面其內(nèi)部的WriteLock可以獲取ReadLock,但是反過來ReadLock想要獲得WriteLock則永遠(yuǎn)都不要想。?
? ? ?(b).WriteLock可以降級為ReadLock,順序是:先獲得WriteLock再獲得ReadLock,然后釋放WriteLock,這時候線程將保持Readlock的持有。反過來ReadLock想要升級為WriteLock則不可能,為什么?參看(a),呵呵.?
???? (c).ReadLock可以被多個線程持有并且在作用時排斥任何的WriteLock,而WriteLock則是完全的互斥。這一特性最為重要,因為對于高讀取頻率而相對較低寫入的數(shù)據(jù)結(jié)構(gòu),使用此類鎖同步機制則可以提高并發(fā)量。?
???? (d).不管是ReadLock還是WriteLock都支持Interrupt,語義與ReentrantLock一致。?
???? (e).WriteLock支持Condition并且與ReentrantLock語義一致,而ReadLock則不能使用Condition,否則拋出UnsupportedOperationException異常。?
下面看一個讀寫鎖的例子:
1 package com.thread;2 3 import java.util.Random;4 import java.util.concurrent.locks.ReentrantReadWriteLock;5 6 public class ReadWriteLockTest {7 public static void main(String[] args) {8 final Queue3 q3 = new Queue3();9 for(int i=0;i<3;i++)
10 {
11 new Thread(){
12 public void run(){
13 while(true){
14 q3.get();
15 }
16 }
17
18 }.start();
19 }
20 for(int i=0;i<3;i++)
21 {
22 new Thread(){
23 public void run(){
24 while(true){
25 q3.put(new Random().nextInt(10000));
26 }
27 }
28
29 }.start();
30 }31 }
32 }
33
34 class Queue3{
35 private Object data = null;//共享數(shù)據(jù),只能有一個線程能寫該數(shù)據(jù),但可以有多個線程同時讀該數(shù)據(jù)。
36 private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
37 public void get(){
38 rwl.readLock().lock();//上讀鎖,其他線程只能讀不能寫
39 System.out.println(Thread.currentThread().getName() + " be ready to read data!");
40 try {
41 Thread.sleep((long)(Math.random()*1000));
42 } catch (InterruptedException e) {
43 e.printStackTrace();
44 }
45 System.out.println(Thread.currentThread().getName() + "have read data :" + data);
46 rwl.readLock().unlock(); //釋放讀鎖,最好放在finnaly里面
47 }
48
49 public void put(Object data){
50
51 rwl.writeLock().lock();//上寫鎖,不允許其他線程讀也不允許寫
52 System.out.println(Thread.currentThread().getName() + " be ready to write data!");
53 try {
54 Thread.sleep((long)(Math.random()*1000));
55 } catch (InterruptedException e) {
56 e.printStackTrace();
57 }
58 this.data = data;
59 System.out.println(Thread.currentThread().getName() + " have write data: " + data);
60
61 rwl.writeLock().unlock();//釋放寫鎖
62 }
63 } ?
Thread-0 be ready to read data! Thread-1 be ready to read data! Thread-2 be ready to read data! Thread-0have read data :null Thread-2have read data :null Thread-1have read data :null Thread-5 be ready to write data! Thread-5 have write data: 6934 Thread-5 be ready to write data! Thread-5 have write data: 8987 Thread-5 be ready to write data! Thread-5 have write data: 8496
下面使用讀寫鎖模擬一個緩存器:
1 package com.thread;2 3 import java.util.HashMap;4 import java.util.Map;5 import java.util.concurrent.locks.ReadWriteLock;6 import java.util.concurrent.locks.ReentrantReadWriteLock;7 8 public class CacheDemo {9 private Map<String, Object> map = new HashMap<String, Object>();//緩存器
10 private ReadWriteLock rwl = new ReentrantReadWriteLock();
11 public static void main(String[] args) {
12
13 }
14 public Object get(String id){
15 Object value = null;
16 rwl.readLock().lock();//首先開啟讀鎖,從緩存中去取
17 try{
18 value = map.get(id);
19 if(value == null){ //如果緩存中沒有釋放讀鎖,上寫鎖
20 rwl.readLock().unlock();
21 rwl.writeLock().lock();
22 try{
23 if(value == null){
24 value = "aaa"; //此時可以去數(shù)據(jù)庫中查找,這里簡單的模擬一下
25 }
26 }finally{
27 rwl.writeLock().unlock(); //釋放寫鎖
28 }
29 rwl.readLock().lock(); //然后再上讀鎖
30 }
31 }finally{
32 rwl.readLock().unlock(); //最后釋放讀鎖
33 }
34 return value;
35 }
36
37 }
轉(zhuǎn)載于:https://www.cnblogs.com/barrywxx/p/8426758.html
總結(jié)
以上是生活随笔為你收集整理的ReentrantReadWriteLock读写锁的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “不惟怀稻粱”下一句是什么
- 下一篇: 御制四十四菊是谁画的啊?