• Java 读写锁 ReentrantReadWriteLock


    参考

    为什么用 ReentrantReadWriteLock

    解决线程安全问题使用ReentrantLock就可以了,但是ReentrantLock是独占锁,某一时刻只有一个线程可以获取该锁,而实际中会有写少读多的场景,显然ReentrantLock满足不了这个需求,所以ReentrantReadWriteLock应运而生。ReentrantReadWriteLock采用读写分离的策略,允许多个线程可以同时获取读锁。读写锁——ReentrantReadWriteLock原理详解

    锁类型 描述
    不加锁 同时可以有多个线程读/写(不安全)
    ReentrantLock 同时只可以有一个线程可以读/写
    ReentrantReadWriteLock 同时可以多个线程读(共享锁)/同时只有一个线程可以写(独占锁)

    代码

    错误实现

    1. 代码如下
    package thread;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * @Author 夏秋初
     * @Date 2022/3/2 10:27
     */
    public class Thread5 {
        public static void main(String[] args) {
            Book book = new Book();
            for (int i = 0; i < 10; i++) {
                final int temp = i;
                new Thread(()->{
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    book.write(temp);
                },String.valueOf(i)).start();
            }
            for (int i = 0; i < 10; i++) {
                final int temp = i;
                new Thread(()->{
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    book.read(temp);
                },String.valueOf(i)).start();
            }
        }
    }
    /**
     * 这样会导致执行时如 write,刚刚开始写入下一步就被别人插队了
     */
    class Book{
        private volatile Map<Integer,String> content = new HashMap(5000);
        public void read(int i){
            System.out.println(Thread.currentThread().getName()+"开始读取");
            System.out.println(Thread.currentThread().getName()+content.get(i));
            System.out.println(Thread.currentThread().getName()+"读取完毕");
        }
        public void write(int i){
            System.out.println(Thread.currentThread().getName()+"开始写入");
            content.put(i, "写入成功");
            System.out.println(Thread.currentThread().getName()+"写入完毕");
        }
    }
    
    1. 执行结果
    Code(点击打开)
    
    6开始写入
    0开始读取
    1开始写入
    9开始写入
    6写入完毕
    4开始写入
    3开始写入
    1开始读取
    9写入完毕
    5开始写入
    5写入完毕
    7开始写入
    8开始写入
    2开始读取
    7开始读取
    8写入完毕
    0开始写入
    0写入完毕
    8开始读取
    5开始读取
    7写入完毕
    9开始读取
    3写入完毕
    4写入完毕
    1写入完毕
    6开始读取
    2开始写入
    2写入完毕
    3开始读取
    4开始读取
    6写入成功
    1写入成功
    3写入成功
    1读取完毕
    4写入成功
    4读取完毕
    2null
    8写入成功
    8读取完毕
    7写入成功
    7读取完毕
    0null
    0读取完毕
    2读取完毕
    9写入成功
    9读取完毕
    5写入成功
    5读取完毕
    6读取完毕
    3读取完毕
    进程已结束,退出代码为 0
    
    

    正确代码

    1. 代码如下
    package thread;
    
    import java.awt.print.Book;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * @Author 夏秋初
     * @Date 2022/3/2 10:27
     */
    public class Thread5 {
        public static void main(String[] args) {
            Book1 book = new Book1();
            for (int i = 0; i < 10; i++) {
                final int temp = i;
                new Thread(()->{
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    book.write(temp);
                },String.valueOf(i)).start();
            }
            for (int i = 0; i < 10; i++) {
                final int temp = i;
                new Thread(()->{
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    book.read(temp);
                },String.valueOf(i)).start();
            }
        }
    }
    /**
     *
     */
    class Book1{
        private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        private ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
        private ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
        private volatile Map<Integer,String> content = new HashMap(5000);
        public void read(int i){
            readLock.lock();
            System.out.println(Thread.currentThread().getName()+"获取读锁完毕");
            try {
                System.out.println(Thread.currentThread().getName()+"开始读取");
    //            System.out.println(Thread.currentThread().getName()+content.get(i));
                System.out.println(Thread.currentThread().getName()+"读取完毕");
            }finally {
                System.out.println(Thread.currentThread().getName()+"释放读锁完毕");
                readLock.unlock();
            }
    
    
        }
        public void write(int i){
            writeLock.lock();
            System.out.println(Thread.currentThread().getName()+"获取写锁完毕");
            try {
                System.out.println(Thread.currentThread().getName()+"开始写入");
                content.put(i, "写入成功");
                System.out.println(Thread.currentThread().getName()+"写入完毕");
            }finally {
                System.out.println(Thread.currentThread().getName()+"释放写锁完毕");
                writeLock.unlock();
            }
        }
    }
    
    
    1. 执行结果
    Code(点击打开)
    
    4获取写锁完毕
    4开始写入
    4写入完毕
    4释放写锁完毕
    6获取写锁完毕
    6开始写入
    6写入完毕
    6释放写锁完毕
    1获取写锁完毕
    1开始写入
    1写入完毕
    1释放写锁完毕
    9获取写锁完毕
    9开始写入
    9写入完毕
    9释放写锁完毕
    2获取写锁完毕
    2开始写入
    2写入完毕
    2释放写锁完毕
    7获取写锁完毕
    7开始写入
    7写入完毕
    7释放写锁完毕
    0获取写锁完毕
    0开始写入
    0写入完毕
    0释放写锁完毕
    3获取写锁完毕
    3开始写入
    3写入完毕
    3释放写锁完毕
    8获取写锁完毕
    8开始写入
    8写入完毕
    8释放写锁完毕
    8获取读锁完毕
    6获取读锁完毕
    6开始读取
    9获取读锁完毕
    9开始读取
    9读取完毕
    8开始读取
    8读取完毕
    6读取完毕
    6释放读锁完毕
    9释放读锁完毕
    8释放读锁完毕
    5获取写锁完毕
    5开始写入
    5写入完毕
    5释放写锁完毕
    7获取读锁完毕
    2获取读锁完毕
    3获取读锁完毕
    1获取读锁完毕
    0获取读锁完毕
    1开始读取
    4获取读锁完毕
    3开始读取
    5获取读锁完毕
    2开始读取
    7开始读取
    2读取完毕
    5开始读取
    3读取完毕
    4开始读取
    1读取完毕
    0开始读取
    1释放读锁完毕
    4读取完毕
    3释放读锁完毕
    5读取完毕
    2释放读锁完毕
    7读取完毕
    5释放读锁完毕
    4释放读锁完毕
    0读取完毕
    7释放读锁完毕
    0释放读锁完毕
    进程已结束,退出代码为 0
    
    
  • 相关阅读:
    力扣算法题—091解码
    力扣算法题—090子集2
    力扣算法题—089格雷编码
    力扣算法题—088合并两个有序数组
    HDU 1509 Windows Message Queue
    HDU 1241 Oil Deposits
    HDU 1096 A+B for Input-Output Practice (VIII)
    HDU 1108 最小公倍数
    HDU 1106 排序
    HDU 1003 Max Sum * 最长递增子序列(求序列累加最大值)
  • 原文地址:https://www.cnblogs.com/xiaqiuchu/p/15954073.html
Copyright © 2020-2023  润新知