JDK1.5以後,提供讀寫鎖。這種鎖支持多線程讀操作不互斥,多線程讀與寫互斥,多線程寫與寫互斥,但讀與讀操作並不互斥。這樣有助於性能的提高。
我們對數據的操作無非兩種:“讀”和“寫”,試想一個這樣的情景,當十個線程同時讀取某個數據時,這個操作應不應該加同步。所以我們使用ReentrantReadWriteLockt它是一個解決單線程寫和多線程讀的理想方法。它採用類似於讀寫分離的思路設定了讀鎖和寫鎖。對於這兩個鎖的訪問保證儘可能大的讀並行和寫互斥。另外,在一定的條件下寫鎖可以轉換成讀鎖,而讀鎖卻不能轉換成寫鎖。
上代碼:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
//資源類
class MyCache{
private Map<String,Object> map = new ConcurrentHashMap<>();
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//讀寫分離
//模擬寫操作
void Write(String key, Object value){
readWriteLock.writeLock().lock();
try{
System.out.println(Thread.currentThread().getName() +"\t 正在寫入..."+",值爲:"+key);
try {
TimeUnit.SECONDS.sleep(2);
}catch (Exception e){
e.printStackTrace();
}
map.put(key,value);
System.out.println(Thread.currentThread().getName() +"\t 寫入完畢!");
}catch (Exception e){
e.printStackTrace();
}finally {
readWriteLock.writeLock().unlock();
}
}
void Read(String key){
readWriteLock.readLock().lock();
try{
System.out.println(Thread.currentThread().getName() +"\t 正在讀取...");
Object res = map.get(key);
System.out.println(Thread.currentThread().getName()+"\t 讀到的值爲:"+res);
}catch (Exception e){
e.printStackTrace();
}finally {
readWriteLock.readLock().unlock();
}
}
}
public class ReadAndWriteLockDemo {
public static void main(String[] args) {
MyCache cache = new MyCache();
//模擬五個線程寫入值
for (int i = 1; i <= 5; i++) {
final int tmp = i;
new Thread(() -> {
cache.Write(tmp + "", tmp + "");
}, "寫線程" + i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",我靜靜地看着它們....");
//模擬五個線程正在讀
for (int i = 1; i <=5 ; i++) {
final int tmp = i;
new Thread(()->{
cache.Read(tmp+"");
},"讀線程"+ i).start();
}
}
}