JUC并发编程快速入门篇(七)—— 读写锁和锁降级

读写锁和锁降级

读写锁

读写锁:ReentrantReadWriteLock

读操作共享资源,写操作独占资源

防止在写操作的过程中被其他线程读取(读取不完整)

缺点:可能造成读的饥饿问题,一直读,没有写

//资源类
class MyCache{

    //创建资源集合
    private volatile Map<String, Object> map = new HashMap<>();
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    //写数据
    public void put(String key,Object value){
        //添加写锁
        readWriteLock.writeLock().lock();

        try {
            System.out.println(Thread.currentThread().getName()+":正在做写操作"+key);
            TimeUnit.MICROSECONDS.sleep(300); //等待300毫秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //解锁
            readWriteLock.writeLock().unlock();
        }

        //放数据
        map.put(key, value);
        System.out.println(Thread.currentThread().getName()+"写完了"+key);
    }

    //取数据
    public Object get(Object key){
        //添加读锁
        readWriteLock.readLock().lock();
        Object result = null;
        try {
            System.out.println(Thread.currentThread().getName()+":正在做读操作"+key);
            TimeUnit.MICROSECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //解锁
            readWriteLock.readLock().unlock();
        }

        //取数据
        result = map.get(key);
        System.out.println(Thread.currentThread().getName()+"取完了"+key);

        return result;
    }
}
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        //创建多个线程放数据
        for (int i = 1; i <=5 ; i++) {
            final int num = i;
            new Thread(()->{
                    myCache.put(num+"", num+"");
            },String.valueOf(i)).start();
        }
        //创建多个线程取数据
        for (int i = 1; i <=5; i++) {
            final int num = i;
            new Thread(()->{
                    myCache.get(num+"");
            },String.valueOf(i)).start();
        }
    }
}

锁降级

降写锁降级为读锁

写锁是可以降级为读锁的;写锁只有一个,当写锁降级为读锁时,所有的都是读。

//写锁降级为读锁
public class Demo1 {
    public void downgrade(){
        //可重入读写锁对象
        ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();//读锁
        ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();//写锁
        System.out.println(Thread.currentThread().getName()+"尝试获取写锁");
        writeLock.lock();
        try{
            System.out.println(Thread.currentThread().getName()+"获取到了写锁");
            System.out.println(Thread.currentThread().getName()+"降级获取读锁");
            readLock.lock(); //降级为读锁
            try{

            }finally {
                readLock.unlock();
            }
        }finally {
            writeLock.unlock();
        }
    }
    public static void main(String[] args) {
        Demo1 demo1 = new Demo1();
        new Thread(()->demo1.downgrade(),"线程1").start();
        new Thread(()->demo1.downgrade(),"线程2").start();

    }
}
上一篇:JUC高并发编程(二)之多线程下载支付宝对账文件


下一篇:JUC并发编程 -- 自定义线程池(阻塞队列)