• 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
    
    
  • 相关阅读:
    Linux五种IO模型性能分析
    并发容器之CopyOnWriteArrayList(转载)
    Web.XML配置详解
    Servlet,过滤器,监听器,拦截器的区别
    JAVA反射机制详解
    Jdk1.6 JUC源码解析(13)-LinkedBlockingQueue
    Jdk1.6 JUC源码解析(12)-ArrayBlockingQueue
    Jdk1.6 JUC源码解析(6)-locks-AbstractQueuedSynchronizer
    Jdk1.6 JUC源码解析(7)-locks-ReentrantLock
    hibernate 其中七种关联关系
  • 原文地址:https://www.cnblogs.com/xiaqiuchu/p/15954073.html
Copyright © 2020-2023  润新知