• 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 }
  • 相关阅读:
    Golang哲学思想
    Outlook与Hotmail的设置
    Android 经验: 5555 端口会被 adb 误认为 emulator
    QT程序探测所需DLL,静态连接和打包
    VS编译的QT程序发布时产生的AppCrash问题
    新语言和旧语言
    MMU和TLB
    FMX的综合评价
    Windows核心编程学习九:利用内核对象进行线程同步
    QListWidget特别简单,但有两种添加item的方式
  • 原文地址:https://www.cnblogs.com/wq3435/p/5958847.html
Copyright © 2020-2023  润新知