天天看點

Java多線程探究-讀寫鎖ReentrantReadWriteLock

讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的通路者劃分成讀者和寫者,讀者隻對共享資源進行讀通路,寫者則需要對共享資源進行寫操作。這種鎖相對于自旋鎖而言,能提高并發性,因為在多處理器系統中,它允許同時有多個讀者來通路共享資源,最大可能的讀者數為實際的邏輯CPU數。寫者是排他性的,一個讀寫鎖同時隻能有一個寫者或多個讀者(與CPU數相關),但不能同時既有讀者又有寫者

讀寫鎖的場景

如果很多線程從一個資料結構讀取資料而很少從線程修改其中資料的話,讀寫鎖是十分有用的。在這種情況下,允許對讀的線程共享通路時合适的。當然寫的線程依然必須是互斥通路的

Java多線程探究-讀寫鎖ReentrantReadWriteLock

ReentrantReadWriteLock是Java的一個讀寫鎖類

ReentrantReadWriteLock.ReadLock readLock()

傳回用于讀取操作的鎖

ReentrantReadWriteLock.WriteLock writeLock()

傳回用于寫入操作的鎖

讀鎖:不排斥讀鎖,排斥寫鎖

寫鎖:排斥其他的寫鎖和讀鎖

class FileObj{
    public String context ;

    public String getContext() {
        return context;
    }

    public void setContext(String context) {
        this.context = context;
    }
}
class ReadThread extends Thread{
    private FileObj fileObj;
    private ReentrantReadWriteLock.ReadLock lock;
    public  ReadThread(FileObj obj , ReentrantReadWriteLock.ReadLock lock){
        this.lock = lock;
        this.fileObj = obj;
    }
    @Override
    public void run(){

        while(true){
            lock.lock();
            try{
                System.out.println(getName()+" 讀取 "+ fileObj.getContext());
                try {
                    Thread.sleep();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }finally {
                lock.unlock();
            }
        }


    }
}
class WriteThread extends  Thread{
    Random random = new Random();
    private FileObj fileObj;
    private ReentrantReadWriteLock.WriteLock lock;
    private String[] str = {"Hello Java","Year Spark","Ok Flume"};
    public  WriteThread(FileObj obj , ReentrantReadWriteLock.WriteLock lock){
        this.lock = lock;
        this.fileObj = obj;
    }
    @Override
    public void run() {
        while (true) {
        lock.lock();
        try {

            String tmp = str[random.nextInt()];
            System.out.println(getName() + " 寫 " + tmp);
            fileObj.setContext(tmp);
            try {
                Thread.sleep();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            lock.unlock();
        }
    }
    }
}
public class ReadAndWriteTest {
    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool();
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        FileObj obj  =  new FileObj();
        obj.setContext("Hello....");
        Thread r1 = new ReadThread(obj,lock.readLock());
        Thread r2 = new ReadThread(obj,lock.readLock());
        Thread r3 = new ReadThread(obj,lock.readLock());

        WriteThread w1 = new WriteThread(obj,lock.writeLock());
        WriteThread w2 = new WriteThread(obj,lock.writeLock());
        WriteThread w3 = new WriteThread(obj,lock.writeLock());

        executorService.execute(r1);
        executorService.execute(r2);
        executorService.execute(r3);
        executorService.execute(w1);
       /* executorService.execute(w1);
        executorService.execute(w3);*/

        executorService.shutdown();


    }
}
           

輸出結果

Java多線程探究-讀寫鎖ReentrantReadWriteLock