1. 概述

lock锁, 基于队列同步器AQS, 实现公平锁、非公平锁

队列同步器AQS可以阅读我这篇文章: 点击传送

实现了Lock接口:

public class ReentrantLock implements Lock

// 加锁 获取不到锁一直等待
void lock();
// 加锁 获取不到锁一直等待 等待过程可以被中断
void lockInterruptibly() throws InterruptedException;
// 尝试获取锁 获取成功返回 true
boolean tryLock();
// 尝试获取锁 等待指定的时间 获取失败返回false
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 解锁
void unlock();

2. 源码阅读

2.1 属性

// 队列同步器,继承了AbstractQueuedSynchronizer
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer

2.2 构造函数

构造函数:

// 默认非公平锁
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    // true:公平锁 false:非公平锁
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

2.3 Sync队列同步器

2.3.1 非公平尝试获取同步状态 nonfairTryAcquire

state为0
● 直接CAS 尝试获取同步状态, compareAndSetState(0, acquires)
● 成功设置当前线程占有锁 setExclusiveOwnerThread(current);
当前线程已经获取锁:
● state下一个值 nextc = c + acquires;
● setState(nextc) 设置值

final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                // 直接尝试获取同步状态
                if (compareAndSetState(0, acquires)) {
                    // 设置当前线程占有锁
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                // 当前线程持有锁 可重入锁 
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

当前线程是否持有锁

protected final boolean isHeldExclusively() {
    return getExclusiveOwnerThread() == Thread.currentThread();
}

获取持有锁的线程

final Thread getOwner() {
    return getState() == 0 ? null : getExclusiveOwnerThread();
}

2.3.2 tryRelease

尝试释放同步状态:

protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            // 持有锁的才可以释放同步状态
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            // 同步状态为0  即要释放锁了
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

2.3.3 NonfairSync、FairSync

NonfairSync 非公平的 Sync , FairSync 公平的 Sync
公平和非公平锁是在 ReentrantLock 重写 AQS tryAcquire 中实现的
● 非公平锁: lock 的时候直接尝试一下获取锁 成功就成功了 失败了才进队列排队获取
● 公平锁:tryAcquire AQS同步队列中没有数据, 即没人排队才可以获取锁

static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

    
        final void lock() {
            // 非公平锁 lock 的时候直接尝试一下获取锁 成功就成功了 失败了才进队列排队获取
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        // 非公平尝试获取同步状态 
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }


        // 尝试获取同步状态
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                // !hasQueuedPredecessors() AQS 同步队列中没有数据, 即没人排队才可以获取锁
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

2.4 ReentrantLock 调用 Sync

public void lock() {
        sync.lock();
   }
  public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
  }
  public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
  }
  public void unlock() {
        sync.release(1);
  }

3. 测试代码

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockStudy {

    static int COUNT = 0;

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        // 加锁
        lock.lock();
        System.out.println(1);
        // 可重入
        lock.lock();
        System.out.println(2);
        // 解锁
        lock.unlock();
        System.out.println(3);
        lock.unlock();
        System.out.println(4);

        new Thread(() -> {
            for (int i=0; i<10000; i++) {
                lock.lock();
                COUNT++;
                lock.unlock();
            }
            System.out.println("end");
        }).start();

        new Thread(() -> {
            for (int i=0; i<10000; i++) {
                lock.lock();
                COUNT++;
                lock.unlock();
            }
            System.out.println("end");
        }).start();;

        while (COUNT != 20000);

        System.out.println(COUNT);
    }
}

ReentrantLock源码阅读_java