读写锁ReadWriteLock

package com.thread_test;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by zhen on 2017-06-05.
 * 读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由jvm自己控制的,你只需要上好相应的锁即可。
 *        如果只读数据,可以多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,切不能同时读取,
 *        那就上写锁。总之,读的时候上读锁,写的时候上写锁
 */
public class ReadWriteLockTest {

    public static void main(String[] args){
        final Queue3 q3 = new Queue3();
        for(int i = 0; i < 3; i++){
            new Thread(new Runnable() {
                public void run() {
                    while(true){
                        q3.get();
                    }
                }
            }).start();
            new Thread(new Runnable() {
                public void run() {
                    while(true){
                        q3.put(new Random().nextInt(10000));
                    }
                }
            }).start();
        }
    }

    /**
     * hibernate的get和load的区别
        User user = session.load(id, User.class);
        User user = session.get(id, User.class);

        get比较耿直,直接查询数据库,返回信息
        load返回代理对象
        User$Proxy extends User{
            private Integer id = id;
            User realUser = null;
            getName(){
                if(realUser == null){
                    realUser = queryByDB(id);
                }
                if(realUser == null){
                    throw new Exception//抛异常
                }
                return realUser.getName();
            }
        }
     */


    /**
     *  ReentrantReadWriteLock
     重入:
        此锁允许reader和writer都按照ReentrantLock的样式重新获取读取锁或写入锁。在写入锁线程保持的所有写入锁都释放后,才允许重入reader使用它们
        此外,writer可以获取读取所,但反过来则不成立。
     锁降级:
        重入还允许从写入锁降级为读取锁,其实现方式是:先获取写入锁,然后获取读取所,最后释放写入锁。但是,从读取锁升级到写入锁是不可能的。

     例子:
        class CachedData {
            Object data;
            volatile boolean cacheValid;
            ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

            void processCacheData(){
        `       rwl.realLock().lock();
                if(!cacheValid){
                    //Must release read lock before acquiring write lock
                    rwl.readLock().unlock();
                    rwl.writeLock().lock();
                    //Recheck state beacuse another thread might write lock
                    //write lock and changed state before we did
                    if(!cacheValue){
                        data = ...
                        cacheValid = true;
                    }
                    //Downgrade by acquiring read lock before releasing write lock
                    rwl.readLock().lock();
                    rwl.writeLock().unLock(); // Unlock write, still hold read
                }
                use(data);
                rwl.readLock().unlock();
             }
        }

     */

}

class Queue3{
    private Object data;
    private ReadWriteLock rwl = new ReentrantReadWriteLock();

    public void put(Object data){
        rwl.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "put data start!");
            Thread.sleep((long)Math.random()*1000);
            this.data = data;
            System.out.println(Thread.currentThread().getName() + "put data end! put data: " + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            rwl.writeLock().unlock();
        }
    }

    public void get(){
        rwl.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "get data start!");
            Thread.sleep((long)Math.random()*1000);
            System.out.println(Thread.currentThread().getName() + "get data end , data is: " + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rwl.readLock().unlock();
        }

    }
}


package com.thread_test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by zhen on 2017-06-05.
 * 模拟缓存
 */
public class CacheDemo {
    private Map<String, Object> cache = new HashMap<String, Object>();

    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public Object getData(String key){
        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 = "aaa";//实际上是queryDB
                        cache.put(key, value);
                    }
                }finally{
                    rwl.writeLock().unlock();
                }
            }
        }finally{
            rwl.readLock().unlock();
        }
        return value;
    }
}

 

posted @ 2017-06-05 13:53  guodaxia  阅读(101)  评论(0)    收藏  举报