【读写锁原来是这么回事】

读写锁

what

读写锁在同一时刻可以允许多个线程访问,但是在写线程访问时,所有的读线程和其他线程均被阻塞.
读写锁维护了一对锁,一个读锁,一个写锁,通过分离读锁和写锁,使得并发性,比一般的排他锁要高.

how

1、读写状态的设计

依赖自定义同步器来实现同步功能,读写状态就是同步器的状态.而读写锁的自定义同步器需要在同步状态(一个整型变量)上维护多个读线程和一个写线程.
在一个整型变量上维护多种状态,就要按位切割使用这个变量.读写锁将变量切分成两个部分,高16位表示读,低16位表示写.

2、写锁的获取与释放

写锁是一个支持可重入的排他锁.如果当前线程已经获取了写锁,则增加写状态.如果当前线程在获取写锁时,读锁已经被获取(读状态不为0)或者该线程不是已经获取写锁的线程,则当前线程进入等待状态,
代码实现ReentrantReadWriteLock的tryAcquire方法
protected final boolean tryAcquire(int acquires){
    Thread current = Thread.currentThread();
    int c = getState();
    int w = exclusiveCount(c);
    if(c != 0){
        //存在读锁或者当前获取线程不是已经获取写锁的线程
        if(w != 0 || current != getExclusiveOwnerThread())
            retrun false;
        if(w + exclusiveCount(acquires) > MAX_COUNT)
            throw new Error("Maximum lock count exceeded");
        setState(c+acquires);
        return true;
    }
    if(writerShouldBlock() || !compareAndSetState(c, c + acquires)){
        return false;
    }
    setExclusiveOwnerThread(current);
    return true;
}

3、读锁的获取与释放

读锁是一个支持重入的共享锁,它能够被多个线程同时获取,在没有其他写线程访问时,读锁总是会被成功地获取,而所做的也只是增加读状态.如果当前线程已经获取了读锁,则增加读状态,如果当前线程获取读锁时,写锁已被其他线程获取,则进入等待状态.
ReentrantReadWriteLock的tryAcquireShared方法:
protected final int tryAcquireShared(int unused){
    for(;;){
        int c = getState();
        int nextc = c + (1<<16);
        if(nextc < c)
            throw new Error("Maximum lock count exceeded");
        if(exclusiveCount(c) != 0 && owner != Thread.currentThread())
            return -1;
        if(compareAndSetState(c,nextc))
            return 1;
    }
}
读锁的每次释放,均减少读状态,减少值是(1<<16).

4、锁降级

指的是写锁降级成读锁.如果当前线程拥有写锁,然后将其释放,最后再获取读锁,这种分段完成的过程不能称之为锁降级.锁降级是指把持住写锁,再获取读锁,随后释放(先前拥有的)写锁的过程    

5、思考

锁降级中,读锁的获取是否必要?
答案是必要的.主要保证数据的可见性,如果当前线程不获取读锁而是直接释放写锁,假设此刻另一个线程A获取了写锁,并修改了数据,那么当前线程无法感知线程A的数据更新.
如果当前线程获取读锁,即遵循锁降级的步骤,则线程T会被阻塞,直到当前线程使用数据并释放读锁之后,线程A才能获取写锁,进行数据更新.

为什么ReentrantReadWriteLock不支持锁升级(把持读锁、获取写锁、释放读锁)?
目的是保证数据的可见性,如果读锁被多个线程获取,其中任一线程成功获取了写锁,并更新数据,则更新对其他获取到的读锁线程是不可见的.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值