Java并发包ReentrantReadWriteLock读写锁

读写锁ReentrantReadWriteLock简介

ReentrantReadWriteLock是ReadWriteLock接口的实现,ReentrantReadWriteLock中有两个静态内部类:ReadLock读锁和WriteLock写锁,这两个锁实现了Lock接口,ReentrantReadWriteLock支持可重入,同步功能依赖自定义同步器(AbstractQueuedSynchronizer)实现,读写状态就是其同步器的同步状态。同步状态由一个整型变量表示,因为这个变量需要表示多个线程的读和写的状态,因此读写锁在实现上将该变量的高16位表示读,低16位表示写。

写锁的获取和释放

写锁WriteLock是支持重进入的排他锁。如果当前线程已经获取了写锁,则增加写状态。如果当前线程在获取读锁时,读锁已经被获取或者该线程不是已获取写锁的线程,则当前线程进入等待状态。读写锁确保写锁的操作对读锁可见。写锁释放每次减少写状态,当前写状态为0时表示写锁已背释放。

读锁的获取与释放

读锁ReadLock是支持重进入的共享锁,它能够被多个线程同时获取,在没有其他写线程访问(写状态为0)时,读锁总是能够被成功地获取,而所做的也只是增加读状态(线程安全)。如果当前线程已经获取了读锁,则增加读状态。如果当前线程在获取读锁时,写锁已经被获取,则进入等待状态。

测试代码
public class LockTest  {
    public static void main(String[] args) {
        final Quen quen = new Quen();
        for(int i=0;i<30;i++){
            new Thread(){
                @Override
                public void run() {
                    quen.get();
                }
            }.start();
            new Thread(){
                @Override
                public void run() {
                    quen.put(new Random().nextInt(1000));
                }
            }.start();
        }
    }
}
class  Quen{
    /*共享数据*/
    private Object data = null;
    /*读写锁*/
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    public void get(){
        /*读锁*/
        lock.readLock().lock();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"------"+data);
        lock.readLock().unlock();
    }
    public void put(Integer i){
        /*写锁*/
        lock.writeLock().lock();
        try {
            Thread.sleep(1000);
            this.data = i;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("写"+Thread.currentThread().getName()+"----"+data);
        lock.writeLock().unlock();
    }
}
多线程读不互斥,写互斥
模拟了一个cache类
class CacheTest{
    /*模拟缓存*/
    private volatile Map cache = new HashMap();
    /*读写锁 解决多线程问题 使用javaee5 的lock解决*/
    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public  Object get(String key){
        /*当o为null的时候有一个线程加了写锁 那么后面再今天的线程 全部阻塞在这里 读锁和写锁是互斥的*/
        rwl.readLock().lock();
        Object o = null;
        try {
            o = cache.get(key);
            if(null == o){
                /*释放读锁 */
                rwl.readLock().unlock();
                /*加上写锁 最开始并发进来的 线程在此争抢写锁,阻塞 写锁与写锁互斥*/
                rwl.writeLock().lock();
                try {
                    /*避免最开始并发线程的再去读数据库*/
                    if(null == o){
                        o = "数据库取数据";
                        cache.put(key,o);
                    }
                }finally {
                    /*释放写锁*/
                    rwl.writeLock().unlock();
                }
                /*加上读锁*/
                rwl.readLock().lock();
            }

        }finally {
            rwl.readLock().unlock();
        }
        return o;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值