java读写锁深入

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33248299/article/details/78814167

一.CachedData

读写锁一个比较好的例子

  • ReentrantReadWriteLock类下的一个CachedData类
  • 不过再谈这个之前我们先来说说hibernate的一个知识
  • Hibernate中有以下两种获取User实体类对象的方法,它们有什么区别?
User user = session.load(id,User.class);
User user = session.get(id,User.class);
  • 第一个方法是不管对象在数据库中是否存在,都会得到一个User对象,这个User对象是一个代理,是一个假的,不是一个真正的User对象,它的内部实际如下
User$Proxy extends User{
            private Integer id = id;
            User readUser = null;
            getName(){ //一个getName的方法
            if(readUser == null){  //当readUser为空时
                  realUser = session.get(id); //送数据库抓取对应id的对象
             if(readlUser == null)  throw execption   //如果不存在就抛异常
       }
              return   realUser.getName();//最后返回
}
} 
  • 第二个是直接去从数据库中把对象抓取出来,如果不存在,值就是null

总结:没有取到数据,第一个就是抛异常,第二个就是值为null,第一个就是一个缓存的对象

  • 类CachedData
class CachedData {//  相当于上面的User$Proxy    用户代理
   Object data;
   volatile boolean cacheValid;
   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {//处理数据
     rwl.readLock().lock();//开读锁
     if (!cacheValid) {  //是否存在缓存的数据,相等于第一次读数据,数据还不存在  我的代理,不是真正有数据,只是一个假的壳子
        // Must release read lock before acquiring write lock
        rwl.readLock().unlock();//释放读锁
        rwl.writeLock().lock();//开写锁
        try {
          // Recheck state because another thread might have
          // acquired write lock and changed state before we did.
          if (!cacheValid) {  //为什么这里又要去判断一次?仔细去想一想!!!!
            data = ...      //如果没有就去查数据
            cacheValid = true;
          }
          // Downgrade by acquiring read lock before releasing write lock
          rwl.readLock().lock();//开读锁
        } finally {
          rwl.writeLock().unlock(); // Unlock write, still hold read
        }
     }

     try {
       use(data);
     } finally {
       rwl.readLock().unlock(); //不论上面代码会不会出问题都会执行释放读锁
     }
   }
 }
  • 其实它就是一个缓存代理

  • 不要小看缓存代理,有些时候面试题就会遇到喊你写一个缓存系统,下面我们可以仿照上面的来一次个缓存系统

二.缓存系统

1.分析

  • 和缓存代理不一样,缓存系统可以装很多个对象
public class CacheDemo {

     private Map<String,Object> cache = new HashMap<String,Object>();//用此代替数据库

     public static void main(String[] args) {

    }

    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public  Object getData(String key){ 
           Object value = cache.get(key);
            if (value == null){ //如果为空就赋值
                value = "aaaa";//实际失去queryDB();
           }
          return value;
    }
}
  • 因为上面的代码仅仅适用于单线程,如果多线程同时去就需要加上synchronized

public class CacheDemo {

     private Map<String,Object> cache = new HashMap<String,Object>();//用此代替数据库

     public static void main(String[] args) {

    }

    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public  synchronized Object getData(String key){ 
           Object value = cache.get(key);
            if (value == null){ //如果为空就赋值
                value = "aaaa";//实际失去queryDB();
           }
          return value;
    }
}
  • 但是你根据读写锁来说多个线程来读,不需要互斥;写的时候才需要互斥,所以我们还要改下代码,可以完全仿照CachedData类来完成
public class CacheDemo {

     private Map<String,Object> cache = new HashMap<String,Object>();

     public static void main(String[] args) {

    }

    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public   Object getData(String key){ //此时是最基础的缓存系统 考虑到多线程就是100分 但是如果你考虑到读写锁问题,就可以得到更高的分数了
        rwl.readLock().lock();
        Object value = null;
        try {
            value = cache.get(key);
            if (value == null) {
                rwl.readLock().unlock();
                rwl.writeLock().lock();
                try {
                    if(value == null) {//想想为什么要加这个判断!!!
                        value = "aaaa";//实际失去queryDB();
                    }
                }finally {
                    rwl.writeLock().unlock();
                }
                rwl.readLock().lock();
            }
        } finally {
            rwl.readLock().unlock();
        }
          return value;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_33248299/article/details/78814167