java并发-ReadWriteLock

219 阅读1分钟

ReadWriteLock

1.读写锁顶层接口
2.和Lock没有关系

ReentrantReadWriteLock

ReadWriteLock的实现类

成员变量:
ReentrantReadWriteLock.ReadLock readerLock (读锁)
ReentrantReadWriteLock.WriteLock writerLock (写锁)
Sync sync (同步器)

读锁和写锁都是实现 Lock 接口

实例代码

private ReadWriteLock lock = new ReentrantReadWriteLock();
	
	
public void method() {

    lock.readLock().lock();
    //lock.writeLock().lock();

    try {

        Thread.sleep(1000);
        System.out.println("hello");

    } catch (Exception e) {
        e.printStackTrace();
    } finally {

        lock.readLock().unlock();
        //lock.writeLock().unlock();

    }

}

ReentrantReadWriteLock构造方法

// fair 表示为是否为公平锁,默认为非公平
public ReentrantReadWriteLock(boolean fair) {
	//创建同步器
    sync = fair ? new FairSync() : new NonfairSync();
    //把当前对象分别传入 到 读写锁中,主要是使用其 同步器
    readerLock = new ReadLock(this);
    writerLock = new WriteLock(this);
}

ReadLock.lock()

public void lock() {
	// 因为读锁为共享锁,所以调用的是同步器的 acquireShared 方法 也就是AQS的这个方法
    sync.acquireShared(1);
}

public final void acquireShared(int arg) {
	//这个方法的结构很熟悉 和 acquire方法的 差不多
    if (tryAcquireShared(arg) < 0)
    	//获取锁失败,进入等待队列
        doAcquireShared(arg);
}

protected final int tryAcquireShared(int unused) {
    /*
     * Walkthrough:
     * 1. If write lock held by another thread, fail.
     * 2. Otherwise, this thread is eligible for
     *    lock wrt state, so ask if it should block
     *    because of queue policy. If not, try
     *    to grant by CASing state and updating count.
     *    Note that step does not check for reentrant
     *    acquires, which is postponed to full version
     *    to avoid having to check hold count in
     *    the more typical non-reentrant case.
     * 3. If step 2 fails either because thread
     *    apparently not eligible or CAS fails or count
     *    saturated, chain to version with full retry loop.
     */
     //获取当前线程
    Thread current = Thread.currentThread();
    //获取 state 的值
    int c = getState();
    //exclusiveCount 是获取独占锁(写锁)的个数 
    //假如 写锁存在 且独占线程不是当前的线程,直接返回 -1  获取锁失败
    if (exclusiveCount (c) != 0 &&
        getExclusiveOwnerThread() != current)
        return -1;
        // 获取读锁的个数
    int r = sharedCount(c);
    // readerShouldBlock 方法用来判断这个锁是否有资格获取锁 这个地方分为 公平锁和非公平锁 不同的实现方式
    // r < MAX_COUNT 表示最大加锁的个数
    //compareAndSetState 表示 CAS 操作是否成功
    if (!readerShouldBlock() &&
        r < MAX_COUNT &&
        compareAndSetState(c, c + SHARED_UNIT)) {
        if (r == 0) {
            firstReader = current;
            firstReaderHoldCount = 1;
        } else if (firstReader == current) {
            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);
}

writeLock.lock()

public void lock() {
    sync.acquire(1);
}

public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

protected final boolean tryAcquire(int acquires) {
    /*
     * Walkthrough:
     * 1. If read count nonzero or write count nonzero
     *    and owner is a different thread, fail.
     * 2. If count would saturate, fail. (This can only
     *    happen if count is already nonzero.)
     * 3. Otherwise, this thread is eligible for lock if
     *    it is either a reentrant acquire or
     *    queue policy allows it. If so, update state
     *    and set owner.
     */
    Thread current = Thread.currentThread();
    int c = getState();
    int w = exclusiveCount(c);
    // c 不为0 表示 有线程持有了 锁,
    // 写锁的 特性,这个锁的线程除非是自己线程,才能重入
    if (c != 0) {
        // (Note: if c != 0 and w == 0 then shared count != 0)
        //必须是 当前线程
        if (w == 0 || current != getExclusiveOwnerThread())
            return false;
        if (w + exclusiveCount(acquires) > MAX_COUNT)
            throw new Error("Maximum lock count exceeded");
        // Reentrant acquire
        setState(c + acquires);
        return true;
    }
    //判断是否有上锁的条件
    // 1. writerShouldBlock 公平的和非公平的不同的处理,假如是公平锁 要判断是否在等待队列中不存在线程
    //2. CAS 操作是否成功
    if (writerShouldBlock() ||
        !compareAndSetState(c, c + acquires))
        return false;
    // 设置独占线程   获取锁成功
    setExclusiveOwnerThread(current);
    return true;
}