public class LockDemo { ArrayList<Integer> arrayList = new ArrayList<>();//定义一个集合 // 定义读锁 ReentrantReadWriteLock.ReadLock readLock = new ReentrantReadWriteLock(true).readLock(); // 定义写锁 ReentrantReadWriteLock.WriteLock writeLock = new ReentrantReadWriteLock(true).writeLock(); public void addEle(Integer ele) { writeLock.lock(); // 获取写锁 arrayList.add(ele); writeLock.unlock(); // 释放写锁 } public Integer getEle(Integer index) { try{ readLock.lock(); // 获取读锁 Integer res = arrayList.get(index); return res; } finally{ readLock.unlock();// 释放读锁 } } }
ReentrantReadWriteLock中的lock方法java
public void lock() { sync.acquire(1); }
AbstractQueuedSynchronizer中的acquire方法安全
public final void acquire(int arg) { // 获取锁失败则进入阻塞队列 if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))**,中的acquireQueued方法和addWaiter方法在前面的文章中都已经进行了详细的解释说明。**ide
ReentrantReadWriteLock中的tryAcquire方法源码分析
protected final boolean tryAcquire(int acquires) { // 获取当前线程 Thread current = Thread.currentThread(); // 获取状态 int c = getState(); // 计算写线程数量就是独占锁的可从入数量 int w = exclusiveCount(c); // 当前同步状态state != 0,说明已经有其余线程获取了读锁或写锁 if (c != 0) { // 当前state不为0,此时:若是写锁状态为0说明读锁此时被占用返回false; // 若是写锁状态不为0且写锁没有被当前线程持有返回false if (w == 0 || current != getExclusiveOwnerThread()) return false; // 判断同一线程获取写锁是否超过最大次数(65535),支持可重入 if (w + exclusiveCount(acquires) > MAX_COUNT) throw new Error("Maximum lock count exceeded"); //更新状态 //此时当前线程已持有写锁,如今是重入,因此只须要修改锁的数量便可 setState(c + acquires); return true; } //到这里说明此时c=0,读锁和写锁都没有被获取 //writerShouldBlock表示是否阻塞 if (writerShouldBlock() || !compareAndSetState(c, c + acquires)) return false; // 设置锁为当前线程全部 setExclusiveOwnerThread(current); return true; } static final class FairSync extends Sync { // 写锁是否应该被阻塞 final boolean writerShouldBlock() { return hasQueuedPredecessors(); } }
写锁的获取过程以下:ui
ReentrantReadWriteLock中的unlock方法线程
public void unlock() { sync.release(1); }
AbstractQueuedSynchronizer中的release方法3d
public final boolean release(int arg) { // 若是返回true 那么释放成功了 if (tryRelease(arg)) { Node h = head; // 若是头部不为空,而且头节点的waitStatus是唤醒状态那么唤醒后继线程 if (h != null && h.waitStatus != 0) // 唤醒后继线程 unparkSuccessor(h); return true; } return false; }
ReentrantReadWriteLock中tryRelease方法code
protected final boolean tryRelease(int releases) { // 若锁的持有者不是当前线程,抛出异常 if (!isHeldExclusively()) // 非法的监控器异常 throw new IllegalMonitorStateException(); // 计算写锁的新线程数 int nextc = getState() - releases; // 若是独占模式重入数为0了,说明独占模式被释放 boolean free = exclusiveCount(nextc) == 0; if (free) // 设置独占线程为空 setExclusiveOwnerThread(null); // 设置写锁的新线程数 // 无论独占模式是否被释放,更新独占重入数 setState(nextc); return free; } protected final boolean isHeldExclusively() { // 若当前线程是当前锁的持有线程那么返回true return getExclusiveOwnerThread() == Thread.currentThread(); }
写锁的释放过程:blog
private volatile int state;
int 类型占有 4个字节一个字节8位,因此 state 一个 32 位,高 16 位 表明读锁 低 16 位表明 写锁。队列
// 0x0000FFFF 16 进制 // 1111111111111111 2 进制 // 65535 10 进制 static final int SHARED_SHIFT = 16; static final int SHARED_UNIT = (1 << SHARED_SHIFT); // 65536 static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1; //65535 // 1111111111111111 static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; // 65535 // 1111111111111111
若是此时同步状态位 c 那么获取写状态 c & EXCLUSIVE_MASK
若是此时同步状态位 c 那么获取读状态 c >>>16 无符号补0,右移16位
*以上即是ReentrantReadWriteLock中写锁的分析,下一篇文章将是***Condition**的分析,若有错误之处,帮忙指出及时更正,谢谢,若是喜欢谢谢点赞加收藏加转发(转发注明出处谢谢!!!)