Lock读写锁技术的妙用

1.面试题1:三个线程读,三个线程写同一个数据

public class ReadWriteLockTest {

    public static void main(String[] args) {
        final Queue3 q3 = new Queue3();
        for(int i=0;i<3;i++){
            //3个读线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        q3.get();
                    }
                }
            }).start();
            //3个写线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    q3.set(new Random().nextInt(10000));
                }
            }).start();
        }
    }
}

class Queue3{
    private Object data = null; //共享数据,只能有一个线程能写该数据,但可以有多个线程同时读
    ReadWriteLock lock = new ReentrantReadWriteLock();
    public void get(){
        try {
            lock.readLock().lock();
            System.out.println(Thread.currentThread().getName()+" be ready to read data!");
            Thread.sleep((long)(Math.random()*1000));
            System.out.println(Thread.currentThread().getName()+" have read data: "+data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.readLock().unlock();
        }
    }
    public void set(Object data){
        try {
            lock.writeLock().lock();
            System.out.println(Thread.currentThread().getName()+" be ready to write data!");
            Thread.sleep((long)(Math.random()*1000));
            this.data = data;
            System.out.println(Thread.currentThread().getName()+" hava write data: "+data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.writeLock().unlock();
        }
        
    }

}

2. 

  Hibernate中两者的区别

  ① User user = session.load(id,User.class);

  ② User user = session.get(id,User.class);

其中②直接从数据库查询,如果查询为空,user为null

其中①在查询时,无论数据路有没有都会得到:User$Proxy 代理类,是一个缓存的User

如果实际的realUser为空则查询数据库,如果从数据库查询出的为空,抛异常,如果不为空

直接返回realUser.getName()  

User$Proxy extends User{
       private Integer id = id;
       User realUser = null;   
    getName(){
        if(realUser == null){
          realUser = session.get(id);
          if(realUser == null)
          throw exception //抛异常
        }
      return realUser.getName();
    } }

3.javaAPI 上的一段代码:

 1 Sample usages. Here is a code sketch showing how to exploit reentrancy to perform lock downgrading after updating a cache (exception handling is elided for simplicity): 
 2 
 3  class CachedData {
 4    Object data;
 5    volatile boolean cacheValid;
 6    ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
 7 
 8    void processCachedData() {  //处理数据
 9      rwl.readLock().lock();  //多个线程并发读,不冲突,只需要上一个读锁
10      if (!cacheValid) {   //检查缓存中有没有数据 if中的代码好比第一次获取数据
11         // Must release read lock before acquiring write lock
12         rwl.readLock().unlock(); //如果一个线程发现没有数据,释放读锁,获取写锁
13         rwl.writeLock().lock();
14         // Recheck state because another thread might have acquired
15         //   write lock and changed state before we did.
16         if (!cacheValid) {
17           data = ...   //实际的写数据逻辑
18           cacheValid = true;  //缓存标志改为true,表示有缓存数据了
19         }
20         // Downgrade by acquiring read lock before releasing write lock
21         rwl.readLock().lock();
22         rwl.writeLock().unlock(); // Unlock write, still hold read
23      }
24 
25      use(data);  //使用数据
26      rwl.readLock().unlock();
27    }
28  }

4.面试题:设计一个缓存系统

 1 public class CacheDemo {
 2     
 3     private Map<String,Object> cache = new HashMap<>();
 4     public static void main(String[] args) {
 5         
 6     }
 7     
 8     private ReadWriteLock rwl = new ReentrantReadWriteLock();
 9     public Object getData(String key){
10         rwl.readLock().lock();  //获取读锁
11         Object value = null;
12         try {
13             value = cache.get(key);
14             if(value == null){
15                 rwl.readLock().unlock();
16                 rwl.writeLock().lock();
17                 try {
18                     if(value == null){
19                         value = "aaa"; //实际是去数据库查询
20                     }
21                 } finally{
22                     rwl.writeLock().unlock();
23                 }
24                 rwl.readLock().lock();
25             }
26         } catch (Exception e) {
27             e.printStackTrace();
28         }finally{
29             rwl.readLock().unlock();  //释放读锁
30         }
31         return value;
32     }
33     
34 }
原文地址:https://www.cnblogs.com/wq3435/p/5958847.html