ReentrantReadWriteLock(重入讀寫鎖)

ReentrantReadWriteLock

 先寫一段原始代碼

public class Demo3 {
    //共享變量
    static int count = 0;
    
    public static void readMethod() {
        try {
            //           爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
            Thread.sleep(1);
            count++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問讀鎖
                Demo3.readMethod();
            }
        });
        thread.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問讀鎖
                Demo3.readMethod();
            }
        });
        thread2.start();
        Thread.sleep(20000);
        System.out.println("result:" + count);
    }
}

預計得值:result: 10000

實際運行得值:result: 9999(經過多次重試,發現小於等於10000)

我們來給它加上鎖ReentrantReadWriteLock

當次兩個線程都使用 讀鎖

public class Demo2 {
    //共享變量
    static int count = 0;
    //    重入讀寫鎖
    static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    //   寫鎖
    static Lock write = rwl.writeLock();
    //    讀鎖
    static Lock read = rwl.readLock();


    //當前方法使用讀鎖
    public static void readMethod() {
        read.lock(); //讀鎖
        try {
            //           爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
            Thread.sleep(1);
            count++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            read.unlock(); //釋放讀鎖
        }
    }

    //當前方法使用讀鎖
    public static void writeMethod() {
        write.lock(); //Other
        try {
            //           爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
            Thread.sleep(1);
            count++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            write.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問讀鎖
                Demo2.readMethod();
            }
        });
        thread.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問讀鎖
                Demo2.readMethod();
            }
        });
        thread2.start();
        Thread.sleep(20000);
        System.out.println("result:" + count);
    }
}

預計得值:result:-10000

實際得值:result:-9999(小於等於10000,如果等於10000,多重試幾次。)

發現:並沒有加鎖效果,讀鎖是共享的(非互斥)

當次兩個線程都使用 寫鎖(代碼基本沒變,就變更了一下訪問的方法)

public class Demo2 {
    //共享變量
    static int count = 0;
    //    重入讀寫鎖
    static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    //   寫鎖
    static Lock write = rwl.writeLock();
    //    讀鎖
    static Lock read = rwl.readLock();


    //當前方法使用讀鎖
    public static void readMethod() {
        read.lock(); //讀鎖
        try {
            //           爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
            Thread.sleep(1);
            count++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            read.unlock(); //釋放讀鎖
        }
    }

    //當前方法使用讀鎖
    public static void writeMethod() {
        write.lock(); //Other
        try {
            //           爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
            Thread.sleep(1);
            count++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            write.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問寫鎖
                Demo2.writeMethod();
            }
        });
        thread.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問寫鎖
                Demo2.writeMethod();
            }
        });
        thread2.start();
        Thread.sleep(20000);
        System.out.println("result:" + count);
    }
}

預計得值:result:10000

實際得值:result:10000多次重試都是:10000)

發現:有加鎖效果,寫鎖是非共享的(互斥)

 當次兩個線程一個使用 寫鎖,另個一使用讀鎖(代碼基本沒變,就變更了一下訪問的方法)

public class Demo2 {
    //共享變量
    static int count = 0;
    //    重入讀寫鎖
    static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    //   寫鎖
    static Lock write = rwl.writeLock();
    //    讀鎖
    static Lock read = rwl.readLock();


    //當前方法使用讀鎖
    public static void readMethod() {
        read.lock(); //讀鎖
        try {
            //           爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
            Thread.sleep(1);
            count++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            read.unlock(); //釋放讀鎖
        }
    }

    //當前方法使用讀鎖
    public static void writeMethod() {
        write.lock(); //Other
        try {
            //           爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
            Thread.sleep(1);
            count++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            write.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問讀鎖
                Demo2.readMethod();
            }
        });
        thread.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                //  當次訪問寫鎖
                Demo2.writeMethod();
            }
        });
        thread2.start();
        Thread.sleep(20000);
        System.out.println("result:" + count);
    }
}

預計得值:result:10000

實際得值:result:10000多次重試都是:10000)

發現:有加鎖效果,讀鎖和寫鎖 是非共享的(互斥)

 總結:

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