读写锁

读写锁

ReentrantReadWriteLock提供读和写分离的锁机制 WriteLock ReadLock
当读线程获取锁时,允许其他线程获取锁,阻塞写线程。
当写线程获取锁时,阻塞所有其他线程。
读写都支持线程重入机制。
锁状态采用按位分割的方式表示读写状态和重入次数。
高16位表示读状态。在获取c == state之后,按位右移16位c>>>16获取读状态。读状态增加时,按位左移增加。state = c + addCount<<16.
写锁状态为c&Ox0000FFFF,写锁状态增加时 直接增加state = c + addCount;

写锁获取方法源码解读
writeLock方法调用独占式获取同步状态的方法 表示写锁独占
public void lock() {
            sync.acquire(1);
        }
        
protected final boolean tryAcquire(int acquires) {
		
            Thread current = Thread.currentThread();
            //  获取当前线程状态值
            int c = getState();
            // 按位与获取写锁状态 
            int w = exclusiveCount(c);
            if (c != 0) {
            // 如果锁状态不为0 表示有线程持有该锁
                // (Note: if c != 0 and w == 0 then shared count != 0)
                // 如果写锁状态为0 表示是读锁被获取 不可获取写锁  如果持有写锁的线程不是当前线程 不可获取写锁
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                // 判断是不是达到最大获取状态
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // Reentrant acquire
                // 不存在读锁 且 持有锁的线程位当前线程 允许重入   此时只有一个线程操作同步状态 无需使用CAS原子操作
                setState(c + acquires);
                return true;
            }
            // 如果当前锁状态为0 表示未有线程持有锁 该线程处于头结点可以去尝试获取锁 
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }



// 写锁释放源码阅读 
protected final boolean tryRelease(int releases) {
// 独占式的写锁释放 判断持有锁的线程是不是当前线程 
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
                // 重入式锁多次释放 直到同步状态为0 
            int nextc = getState() - releases;
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
                setExclusiveOwnerThread(null);
            setState(nextc);
            return free;
        }
        
// 获取读锁通过共享式的获取同步状态来获取 
public void lock() {
            sync.acquireShared(1);
        }

protected final int tryAcquireShared(int unused) {
            Thread current = Thread.currentThread();
            // 获取当前锁状态
            int c = getState();
            // exclusiveCount(c)获取写锁状态 如果不为0 并且持有锁的线程不是当前线程 获取失败 
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            // 获取读锁状态 r
            int r = sharedCount(c);
            // 如果允许获取读锁 且 读锁状态未达到最大值 且设置新state值成功 则获取成功
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                if (r == 0) {
                	// 如果原本无读锁 则设置当前线程为firstReader  firstReaderHoldCount=1
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                	// firstReader读锁为当前锁   添加进入次数
                    firstReaderHoldCount++;
                } else {
                	// 
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return 1;
            }
            return fullTryAcquireShared(current);
        }
锁升级和锁降级

读写锁支持锁降级 不支持锁升级 因为写锁是独占式的 排斥其他所有读锁和写锁 包含自己获取的读锁

/**
     * 锁升级  不支持
     */
    public static void readAndWriter(){
        try{
            readLock.lock();
            System.out.println(Thread.currentThread().getName()+" get readLock");
            try{
                Thread.sleep(10000);
                // 读锁被自己获取了  获取写锁也会等待
                writeLock.lock();
                System.out.println(Thread.currentThread().getName()+" get writeLock");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                readLock.unlock();
                System.out.println(Thread.currentThread().getName()+" release readLock");
            }
        }finally {
            writeLock.unlock();
            System.out.println(Thread.currentThread().getName()+" writeLock readLock");
        }
    }

输出结果:
Thread-0 get readLock

表明一个线程先获取读锁在获取写锁时,写锁获取会阻塞。

/**
     * 锁降级 支持的
     */
    public static void writeAndRead(){
        try{
            writeLock.lock();
            System.out.println(Thread.currentThread().getName()+" get writeLock");
            try{
                // 写锁被自己获取  还能够获取读锁
                readLock.lock();
                System.out.println(Thread.currentThread().getName()+" get readLock");

            }finally {
                writeLock.unlock();
                System.out.println(Thread.currentThread().getName()+" release writeLock");
            }

        }finally {
            readLock.unlock();
            System.out.println(Thread.currentThread().getName()+" release readLock");
        }
    }

输出结果:
Thread-0 get writeLock
Thread-0 get readLock
Thread-0 release writeLock
Thread-0 release readLock
一个线程写锁获取成功之后还是能够获取读锁的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值