• java中的读/写锁


    读写锁接口:ReadWriteLock,它的具体实现类为:ReentrantReadWriteLock

    使用场景:

    对于一个资源,读读能共存,读写不能共存,写写不能共存。

    锁降级:从写锁变成读锁;

    锁升级:从读锁变成写锁。

    ReentrantReadWriteLock不支持锁升级,支持锁降级

    ReadWriteLock rtLock = new ReentrantReadWriteLock();
     rtLock.readLock().lock();
     System.out.println("get readLock.");
     rtLock.writeLock().lock();
     System.out.println("blocking");

    会死锁

    ReadWriteLock rtLock = new ReentrantReadWriteLock();
    rtLock.writeLock().lock();
    System.out.println("writeLock");
    
    rtLock.readLock().lock();
    System.out.println("get read lock");

    不会死锁

    案例应用:

    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class CacheDemo {
        /**
         * 缓存器,这里假设需要存储1000左右个缓存对象,按照默认的负载因子0.75,则容量=750,大概估计每一个节点链表长度为5个
         * 那么数组长度大概为:150,又有雨设置map大小一般为2的指数,则最近的数字为:128
         */
        private Map<String, Object> map = new HashMap<>(128);
        private ReadWriteLock rwl = new ReentrantReadWriteLock();
        public static void main(String[] args) {
    
        }
        public Object get(String id){
            Object value = null;
            rwl.readLock().lock();//首先开启读锁,从缓存中去取
            try{
                value = map.get(id);
                if(value == null){  //如果缓存中没有释放读锁,上写锁
                    rwl.readLock().unlock();
                    rwl.writeLock().lock();
                    try{
                        if(value == null){ //防止多写线程重复查询赋值
                            value = "redis-value";  //此时可以去数据库中查找,这里简单的模拟一下
                        }
                        rwl.readLock().lock(); //加读锁降级写锁,不明白的可以查看上面锁降级的原理与保持读取数据原子性的讲解
                    }finally{
                        rwl.writeLock().unlock(); //释放写锁
                    }
                }
            }finally{
                rwl.readLock().unlock(); //最后释放读锁
            }
            return value;
        }
    }

    如果不使用锁降级功能,如先释放写锁,然后获得读锁,在这个get过程中,可能会有其他线程竞争到写锁 或者是更新数据 则获得的数据是其他线程更新的数据,可能会造成数据的污染,即产生脏读的问题。

  • 相关阅读:
    noi.ac #30 思维
    bzoj 2330: [SCOI2011]糖果
    bzoj 2326: [HNOI2011]数学作业
    bzoj 2324: [ZJOI2011]营救皮卡丘
    bzoj 2301: [HAOI2011]Problem b
    bzoj 2286: [Sdoi2011消耗战
    bzoj 2282: [Sdoi2011]消防
    bzoj 2257: [Jsoi2009]瓶子和燃料
    bzoj 2245: [SDOI2011]工作安排
    bzoj 2244: [SDOI2011]拦截导弹
  • 原文地址:https://www.cnblogs.com/L-a-u-r-a/p/8569749.html
Copyright © 2020-2023  润新知