读写锁ReentrantReadWriteLock学习

一、思路

1、先开启读锁,获取缓存的数据 value

2、对value进行判断,若为空,则关闭读锁;开启写锁,并获取缓存数据value(其他线程可能赋值),若value为空,则对缓存赋值。并将写锁降级为读锁。

3、不为空,则获取value,并关闭读锁。

注意:读写锁的关键是否有缓存值,有进行什么操作,没有进行什么操作。这个过程要考虑别的线程赋值问题,再进行相应的操作。

二、代码示例

// 读写锁
public static void ReentrantReadWriteLockCacheSystem() {

    //这里为了实现简单,将缓存大小设置为4。
    Map cacheMap = new HashMap<>(4);
    ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    for (int i = 0; i < 20; i++) { //同时开启20个线程访问缓存

        final String key = String.valueOf(i % 4);
        log.info(Thread.currentThread().getName()+"key:{}",key);
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    //①读取缓存时获取读锁
                    readWriteLock.readLock().lock();
                    //获取读锁后通过key获取缓存中的值
                    String valueStr = cacheMap.get(key);
                    log.info("value:{}",valueStr);
                    //缓存值不存在
                    if (valueStr == null) {
                        //③释放读锁后再尝试获取写锁
                        // 读不到数据,就关闭读锁,开启写锁
                        readWriteLock.readLock().unlock();  //关闭读锁
                        try {
                            //④获取写锁来写入不存在的key值,
                            readWriteLock.writeLock().lock();
                            valueStr = cacheMap.get(key);
                            log.info("key:{}"+key+",关闭读锁后value:{}",valueStr);
                            if (valueStr == null) {
                                valueStr = key + " --- value";
                                log.info("为锁赋值:{}",valueStr);
                                cacheMap.put(key, valueStr); //写入值
                                System.out.println(Thread.currentThread().getName() + " --------- put " + valueStr);
                            }
                            // ⑥锁降级,避免被其他写线程抢占后再次更新值,保证这一次操作的原子性
                            readWriteLock.readLock().lock();
                            log.info("读锁操作:{}"+key);
                            System.out.println(Thread.currentThread().getName() + " --------- get new " + valueStr);
                        } finally {
                            log.info("写锁操作:{}",key);
                            readWriteLock.writeLock().unlock(); //⑤释放写锁
                        }

                    } else {
                        System.out.println(Thread.currentThread().getName() + " ------ get cache value");
                    }
                } finally {
                    log.info("释放读锁:{}",key);
                    readWriteLock.readLock().unlock();  //②释放读锁
                }
            }
        }, String.valueOf(i));
        thread.start();
    }
}

三、涉及的技术

   1、lombok、多线程的读写类ReentrantReadWriteLock

    2、项目demo。https://github.com/krycai/MultiThread  的类LockDemo2

你可能感兴趣的:(多线程,读写锁)