Java讀寫鎖的基本使用

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();
        }

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章