ReentrantReadWriteLock 读写锁获取与释放源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/programmer_at/article/details/78910614

ReentrantReadWriteLock 读写锁

构造函数

与ReentrantLock相类似, 其自定义同步器Sync分为公平锁FairSync与非公平锁NonfairSync的两种.

默认为NonfairSync

public ReentrantReadWriteLock() {
        this(false);
    }

public ReentrantReadWriteLock(boolean var1) {
    this.sync = (ReentrantReadWriteLock.Sync)(var1?new ReentrantReadWriteLock.FairSync():new ReentrantReadWriteLock.NonfairSync());
    this.readerLock = new ReentrantReadWriteLock.ReadLock(this);
    this.writerLock = new ReentrantReadWriteLock.WriteLock(this);
}

同步状态

同步状态表示锁被一个线程重复获取的次数. 而ReentrantReadWriteLock的自定义同步器Sync需要在同步状态(一个整型变量)上维护多个读线程和一个写线程的状态. 读写锁通过将该整型变量”按位切割使用”, 切分为两个部分, 高16位表示读, 低16位表示写
image

//ReentrantReadWriteLock.java: ReentrantReadWriteLock.Sync 
// 获取写同步锁状态
static int exclusiveCount(int var0) {
    return var0 & '\uffff';
}

// 获取读同步锁状态
static int sharedCount(int var0) {
            return var0 >>> 16;
        }

WriteLock 写锁

获取

获取锁的全过程: ReentrantReadWriteLock.WriteLock.lock() –> this.sync.acquire(1) (即 AbstractQueueSynchronizer.acquire(int var1)) –> ReentrantReadWriteLock.WriteLock.tryAcquire(1)

  • 获取写锁成功: ReentrantReadWriteLock.WriteLock.tryAcquire(1)返回true, AbstractQueueSynchronizer.acquireQueued()返回true
  • 获取写锁阻塞: ReentrantReadWriteLock.WriteLock.tryAcquire(1)返回false, AbstractQueueSynchronizer.acquireQueued()阻塞, 自旋锁
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
public void lock() {
            this.sync.acquire(1);
        }

this.sync为ReentrantReadWriteLock自定义同步器Sync的实例(也是ReentrantReadWriteLock实例的成员变量), 是AbstractQueueSynchronizer的子类.

// AbstractQueueSynchronizer.java AbstractQueueSynchronizer
public final void acquire(int var1) {
        if(!this.tryAcquire(var1) && this.acquireQueued(this.addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE), var1)) { 
            selfInterrupt();
        }

    }

由于this.sync重写了父类的tryAcquire()等方法, 所以this.tryAcquire会调用重写后的方法

// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
protected final boolean tryAcquire(int var1) {
    Thread var2 = Thread.currentThread();
    int var3 = this.getState();
    int var4 = exclusiveCount(var3);  // 获取写状态
    if(var3 != 0) { 
        // 支持重进入
        if(var4 != 0 && var2 == this.getExclusiveOwnerThread()) {
            if(var4 + exclusiveCount(var1) > '\uffff') {
                throw new Error("Maximum lock count exceeded");
            } else {
                this.setState(var3 + var1);
                return true;
            }
        } else {
            //存在读锁或者当前获取线程不是已经获取写锁的线程
            // var4 == 0 || var2 != this.getExclusiveOwnerThread()
            return false;
        }
    } else if(!this.writerShouldBlock() && this.compareAndSetState(var3, var3 + var1)) { // 当前无线程获取写锁 
        this.setExclusiveOwnerThread(var2);
        return true;
    } else {
        return false;
    }
}

AbstractQueueSynchronizer.acquire():
image

释放

释放的全过程: ReentrantReadWriteLock.WriteLock.unlock() –> this.sync.release(1) (即 AbstractQueueSynchronizer.release(int var1)) –> ReentrantReadWriteLock.WriteLock.tryRelease

  • 只有获取写锁线程(同步队列中头节点)全部释放写锁后(ReentrantReadWriteLock.WriteLock.tryRelease返回true), 才会唤醒同步队列中头节点的后继节点(AbstractQueueSynchronizer.release中断unparkSuccessor)

  • 跟ReentrantLock释放锁的逻辑是一样.

// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
public void unlock() {
    this.sync.release(1);
}
// AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
public final boolean release(int var1) {
        if(this.tryRelease(var1)) {
            AbstractQueuedSynchronizer.Node var2 = this.head;
            //  waitStatus为0说明是初始化的空队列
            if(var2 != null && var2.waitStatus != 0) {
                this.unparkSuccessor(var2);  // 唤醒同步队列中头节点的后继节点
            }

            return true;
        } else {
            return false;
        }
    }

因为写锁支持重进入,所以只有多次获取了写锁的线程持有的写锁完全是否完毕才会返回true

// ReentrantReadWriteLock.java: ReentrantReadWriteLock.WriteLock
protected final boolean tryRelease(int var1) {
            if(!this.isHeldExclusively()) {
                throw new IllegalMonitorStateException();
            } else {
                int var2 = this.getState() - var1;
                boolean var3 = ( exclusiveCount(var2) == 0 );
                if(var3) {
                    // 写锁完全释放完毕(=0), 因为写锁支持重进入
                    this.setExclusiveOwnerThread((Thread)null);
                }

                // 减少写锁次数
                this.setState(var2);
                return var3;
            }
        }

ReadLock 读锁

获取

获取读锁全过程: ReentrantReadWriteLock.ReadLock.lock() –> this.sync.acquireShared(1); (即, AbstractQueueSynchronizer.acquireShared)

  • 获取成功: this.sync.acquireShared(1)马上返回
  • 获取阻塞: 获取读锁失败(ReentrantReadWriteLock.Sync.tryAcquireShared(1) < 0) –> 进入同步队列等待(AbstractQueueSynchronizer.doAcquireShared(1)), 只有同步队列中该线程的前驱节点为同步队列的头节点, 并且能够成获取读锁(ReentrantReadWriteLock.Sync.tryAcquireShared(1) > 0)
//ReentrantReadWriteLock.Java: ReentrantReadWriteLock.ReadLock
public void lock() {
    this.sync.acquireShared(1);
}
AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
public final void acquireShared(int var1) {
        if(this.tryAcquireShared(var1) < 0) { // 获取读锁失败则进入同步队列等待
            this.doAcquireShared(var1);
        }

    }
//ReentrantReadWriteLock.Java: ReentrantReadWriteLock.Sync
protected final int tryAcquireShared(int var1) {
    Thread var2 = Thread.currentThread();
    int var3 = this.getState();

    // 写锁已被其他线程获取
    if(exclusiveCount(var3) != 0 && this.getExclusiveOwnerThread() != var2) {
        return -1;
    } else {
        int var4 = sharedCount(var3);

        // 读锁处于非阻塞状态 && 读锁没有达最大值 && 修改读锁状态成功(读锁加1: var3 + 65536 <==> var + (1<<16) )
        if(!this.readerShouldBlock() && var4 < '\uffff' && this.compareAndSetState(var3, var3 + 65536)) {
            // 读锁首次获取
            if(var4 == 0) {
                this.firstReader = var2;
                this.firstReaderHoldCount = 1;
            } else if(this.firstReader == var2) {  // firstReader线程再次获得读锁
                ++this.firstReaderHoldCount;
            } else {  // 非firstReader线程

                // 保存当前线程读取锁的次数
                ReentrantReadWriteLock.Sync.HoldCounter var5 = this.cachedHoldCounter;  // cachedHoldCounter存储当前线程获取读锁的次数

                // 3. 当前线程非首次获取读锁
                if(var5 != null && var5.tid == ReentrantReadWriteLock.getThreadId(var2)) {
                    if(var5.count == 0) {
                        this.readHolds.set(var5);
                    }
                } else {
                    // 1. 当前线程首次获取读锁, 新建cachedHoldCounter (ThreadLocal: get() --> setInitialValue() --> createMap())
                    this.cachedHoldCounter = var5 = (ReentrantReadWriteLock.Sync.HoldCounter)this.readHolds.get();
                }

                // 2. 更新当前线程获取读锁的次数
                ++var5.count;
            }

            return 1;
        } else {
            return this.fullTryAcquireShared(var2);
        }
    }
}
//AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
private void doAcquireShared(int var1) {
        // 将当前节点加入同步队列
        AbstractQueuedSynchronizer.Node var2 = this.addWaiter(AbstractQueuedSynchronizer.Node.SHARED);
        boolean var3 = true;

        try {
            boolean var4 = false;

            while(true) {
                AbstractQueuedSynchronizer.Node var5 = var2.predecessor();
                if(var5 == this.head) {  // 前驱节点为头节点
                    int var6 = this.tryAcquireShared(var1);
                    if(var6 >= 0) {  // 获取读锁成功, 否则自旋等待读锁
                        // 更新头节点, 会往后面结点传播唤醒的操作,保证剩下等待的线程能够尽快 获取到剩下的许可。
                        this.setHeadAndPropagate(var2, var6);  
                        var5.next = null;
                        if(var4) {
                            selfInterrupt();
                        }

                        var3 = false; 
                        return;
                    }
                }

                if(shouldParkAfterFailedAcquire(var5, var2) && this.parkAndCheckInterrupt()) {
                    var4 = true;
                }
            }
        } finally {
            if(var3) { // 获取读锁失败, 取消获取读锁
                this.cancelAcquire(var2);
            }

        }
    }

释放

ReentrantReadWriteLock.ReadLock.unlock() –> this.sync.releaseShared(1) 即, AbstractQueueSynchronizer.releaseShared(1) –> ReentrantReadWriteLock.Sync.tryReleaseShared() –>(倘若线程所持有的所有读锁都释放完毕) AbstractQueueSynchronizer.doReleaseShared()

  • 读锁释放成功: 当前线程所持有的所有读锁都释放完毕, this.sync.releaseShared(1)返回true; 倘若知只是释放了其中一个读锁, this.sync.releaseShared(1)返回false
  • 读锁释放重试: AbstractQueueSynchronizer.doReleaseShared()
// ReentrantReadWriteLock.java: ReentrantReadWriteLock.ReadLock
public void unlock() {
    this.sync.releaseShared(1);
}

只有当前线程所持有的所有读锁都释放完毕, 才会返回true

// AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
public final boolean releaseShared(int var1) {
        if(this.tryReleaseShared(var1)) { // 当前线程所持有的所有读锁都释放完毕, 当前队列从同步队列的移出, 修改同步队列头节点
            this.doReleaseShared();  // 唤醒同步队列的后继节点
            return true;
        } else {
            return false;
        }
    }

只有当前线程所持有的所有读锁都释放完毕, 才会返回true

// ReentrantReadWriteLock.java: ReentrantReadWriteLock.Sync
protected final boolean tryReleaseShared(int var1) {
            Thread var2 = Thread.currentThread();
            int var4;

            // 当前线程的读锁状态
            if(this.firstReader == var2) {
                if(this.firstReaderHoldCount == 1) {
                    this.firstReader = null;
                } else {
                    --this.firstReaderHoldCount;
                }
            } else {

                ReentrantReadWriteLock.Sync.HoldCounter var3 = this.cachedHoldCounter;
                if(var3 == null || var3.tid != ReentrantReadWriteLock.getThreadId(var2)) {
                    var3 = (ReentrantReadWriteLock.Sync.HoldCounter)this.readHolds.get();
                }

                var4 = var3.count;
                // 当前线程所有读锁都已经释放, 从读锁的同步队列中移出
                if(var4 <= 1) {
                    this.readHolds.remove();
                    if(var4 <= 0) {
                        throw this.unmatchedUnlockException();
                    }
                }

                --var3.count;
            }

            int var5;
            do {
                var5 = this.getState();
                var4 = var5 - 65536;  // 修改当前读锁状态: var5 - (1<<16)
            } while(!this.compareAndSetState(var5, var4));

            return var4 == 0;
        }
//AbstractQueueSynchronizer.java: AbstractQueueSynchronizer
private void doReleaseShared() {
        while(true) {
            AbstractQueuedSynchronizer.Node var1 = this.head;
            if(var1 != null && var1 != this.tail) {
                int var2 = var1.waitStatus;
                if(var2 == -1) { // 1. 后继节点等待唤醒
                    if(!compareAndSetWaitStatus(var1, -1, 0)) {
                        continue;
                    }

                    this.unparkSuccessor(var1); // 2. 唤醒后继节点
                } else if(var2 == 0 && !compareAndSetWaitStatus(var1, 0, -3)) { 
                // 3. 后续结点会传播唤醒的操作
                    continue;
                }
            }

            if(var1 == this.head) {  // 当前节点为同步对列的头节点
                return;
            }
        }
    }

这里是对本文涉及的同步队列操作进行详细说明

猜你喜欢

转载自blog.csdn.net/programmer_at/article/details/78910614