讀寫所概念
我們平常通過鎖來對進程進行協同。
但如果在讀多寫少的場景(可以允許多個讀同時進行不影響)也使用普通的鎖,會嚴重影響程序的性能。
為了解決這個問題引入讀寫鎖,請看下面場景1:
1.讀線程:如果thread在寫resource的時候,其他read和write線程都終止。
2.寫線程:可以允許多個thread同時讀取resource。
我們先澄清一下定義和規則:
a.如果一個線程是讀取資源就叫讀線程,如果是寫資源就叫寫線程。
b.為了實現上面的“場景1”的要求,在代碼中我們需要在讀操作加上read鎖,在寫操作加上write鎖。
讀寫所機制偽代碼講解
ReadWriteLock wrLock = new ReentrantReadWriteLock();
read線程執行獲取讀鎖:
get(){
wrlock.getReadLock.lock();
...println(Thread.currentThread().getName() + " 準備讀數據!");
/* 休眠 */
...println(Thread.currentThread().getName() + "讀取完畢 :" + data);
wrlock.getReadLock.unlock();
}
write線程執行獲取寫鎖:
put(){
wrlock.getWriteLock.lock();
...println(Thread.currentThread().getName() + " 準備寫入數據!");
/* 休眠 */
...println(Thread.currentThread().getName() + "寫入完畢");
wrlock.getWriteLock.unlock();
}
運行結果為:
/*******a b 兩個線程同時執行*****/
a準備讀取數據
b準備讀取數據
a讀取完畢
b讀取完畢
/一次只有一個寫線程,所以先c執行再d執行*/
// c線程執行
c準備寫入數據!
c寫入完畢
// d線程執行
d準備寫入數據!
d寫入完畢
如何使用
加鎖是使其資源原子性,不管其資源是內存還是數據庫。
我們并發控制的是資源不是代碼?比如如下代碼如何協同:
A: code1 code2
B: code1 code2
想象執行序列:
a).A,B線程都執行到code1 :A :code1 B:code1。
b).A執行到code1,B執行到code2。
不管執行序列如何,我們必須通過同一個lock對象來協同線程的訪問。
在該排他代碼的地方加 write鎖,在非排他地方加read鎖。
參考
http://tutorials.jenkov.com/java-concurrency/read-write-locks.html