JDK15源码(四):ReentrantLock

ReentrantLock的出现

在JDK1.6以前,synchronized是重量级锁,需要调用操作系统的函数实现。Doug Lea就开发了JUC(java.util.concurrent工具包),可以在API级别对线程进行同步,后面sun公司对synchronized进行了优化。

LockSupport.park & LockSupport.unpark

调用LockSupport的park方法会堵塞线程。底层是调用Unsafe类的park方法。要重新恢复线程需要调用LockSupport.unpark(thread)方法。

public static void park() {
    
    
    U.park(false, 0L);
}

Unsafe类的 park()方法:如果isAbsolute为false,堵塞时间单位是纳秒;isAbsolute为true,堵塞时间单位是毫秒;time是堵塞时间。

public native void park(boolean isAbsolute, long time);

公平锁和非公平锁

ReentrantLock支持公平锁和非公平锁,默认是非公平锁,可以在实例化ReentrantLock时指定使用公平锁还是非公平锁。

//ReentrantLock的final属性,在构造函数进行初始化,Sync是ReentrantLock定义的抽象静态内部类
private final Sync sync;

//内部类Sync继承抽象队列同步器
abstract static class Sync extends AbstractQueuedSynchronizer{
    
    }

//无参构造函数,指定使用非公平锁
public ReentrantLock() {
    
    
    sync = new NonfairSync();
}

//如果fair为true,表示使用公平锁;如果fair为false,表示使用非公平锁
public ReentrantLock(boolean fair) {
    
    
    sync = fair ? new FairSync() : new NonfairSync();
}

//调用Unsafe类的cas方法修改ReentrantLock的state变量的值。
protected final boolean compareAndSetState(int expect, int update) {
    
    
        return U.compareAndSetInt(this, STATE, expect, update);
    }

//非公平锁实现
static final class NonfairSync extends Sync {
    
    
   //成功持有锁返回true,失败返回false。
    final boolean initialTryLock() {
    
    
        //获取当前线程
        Thread current = Thread.currentThread();
        //判断修改state的值是否成功
        if (compareAndSetState(0, 1)) {
    
    
            //将锁的持有者修改为当前线程
            setExclusiveOwnerThread(current);
            //成功持有锁返回true
            return true;
        //修改失败,判断持有锁的是否是当前线程    
        } else if (getExclusiveOwnerThread() == current) {
    
    
            //如果是当前线程持有锁,可重入,计数加1。
            int c = getState() + 1;
            if (c < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            //设置state的值    
            setState(c);
            //成功持有锁返回true
            return true;
        } else
            //持有锁失败返回false
            return false;
    }

    /**
     * 调用initialTryLock方法后,非可重入
     */
    protected final boolean tryAcquire(int acquires) {
    
    
        //如果当前锁没有被其他线程持有,并且当前线程修改state值为acquires成功
        if (getState() == 0 && compareAndSetState(0, acquires)) {
    
    
            //把锁的持有者修改为当前线程
            setExclusiveOwnerThread(Thread.currentThread());
            //持有锁成功返回true。
            return true;
        }
        //持有锁失败返回false。
        return false;
    }
}

//公平锁实现
static final class FairSync extends Sync {
    
    
    /**
     * 锁没有被占用并且等待队列为空才会获取锁,不可重入
     */
    final boolean initialTryLock() {
    
    
        //当前线程
        Thread current = Thread.currentThread();
        //获取state变量的值
        int c = getState();
        //如果state等于0,表示锁没有被其他线程占有
        if (c == 0) {
    
    
            //如果当前没有其他线程在等待获取,并且cas修改state值成功
            if (!hasQueuedThreads() && compareAndSetState(0, 1)) {
    
    
                //将锁的持有者修改为当前线程
                setExclusiveOwnerThread(current);
                //持有锁成功返回true。
                return true;
            }
        } else if (getExclusiveOwnerThread() == current) {
    
    
            if (++c < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            //重入,修改state变量的值    
            setState(c);
            //持有锁成功返回true。
            return true;
        }
        //持有锁失败返回false。
        return false;
    }

    /**
     * 只有当前线程是等待队列的头结点或者等待队列是空,才能获取
     */
    protected final boolean tryAcquire(int acquires) {
    
    
         //判断锁是否被持有,是否是等待队列的头结点(或者等待队列为空),cas修改state的值是否成功
        if (getState() == 0 && !hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
    
    
            //将锁的持有者修改为当前线程
            setExclusiveOwnerThread(Thread.currentThread());
            //获取锁成功返回true。
            return true;
        }
        //获取锁失败返回false。
        return false;
    }
}

lock()

占用锁

final void lock() {
    
    
    //如果第一次获取锁失败,会进行第二次尝试
    if (!initialTryLock())
        acquire(1);
}

public final void acquire(int arg) {
    
    
     //判断是否获取成功
    if (!tryAcquire(arg))
        acquire(null, arg, false, false, false, 0L);
}
/**
 * node null 除非有重新获取条件
 * arg 获取参数
 * shared true表示共享模式 false表示独占模式
 * interruptible 是否中断,中断的时候返回负数
 * timed 是否使用等待时间
 * time 如果使用等待时间,设置超时时间
 * 如果获取成功,这个方法会返回正数,如果超时返回0,如果中断返回负数 
 */
final int acquire(Node node, int arg, boolean shared,
                      boolean interruptible, boolean timed, long time) {
    
    
    Thread current = Thread.currentThread();
    byte spins = 0, postSpins = 0;   
    boolean interrupted = false, first = false;
    Node pred = null;   

    for (;;) {
    
    
        //第一次循环:first = false,node = null,pred = null,head = null
        //第二次循环:first = false,node != null,node.prev = null, pred = null, head = null
        //第三次循环:first = false,node != null,node.prev = null, pred = null, head != null
        //第四次循环:first = false,node != null,node.prev != null, pred != null, head = pred⇒ first = true
        //第五次循环:first = true
        if (!first && (pred = (node == null) ? null : node.prev) != null &&
            !(first = (head == pred))) {
    
    
            if (pred.status < 0) {
    
    
                cleanQueue(); 
                continue;
            } else if (pred.prev == null) {
    
    
                Thread.onSpinWait(); 
                continue;

            }
        }
        //第一次循环first = false,pred = null, node = null
        //第二次循环first = false,pred = null, node != null
        if (first || pred == null) {
    
    
            boolean acquired;
            try {
    
    
                if (shared)
                    //共享锁
                    acquired = (tryAcquireShared(arg) >= 0);
                else
                    //独占锁
                    acquired = tryAcquire(arg);
            } catch (Throwable ex) {
    
    
                cancelAcquire(node, interrupted, false);
                throw ex;
            }
            //如果有其他线程占有锁,返回false
            if (acquired) {
    
    
                if (first) {
    
    
                    node.prev = null;
                    head = node;
                    pred.next = null;
                    node.waiter = null;
                    if (shared)
                        signalNextIfShared(node);
                    if (interrupted)
                        current.interrupt();
                }
                return 1;
            }
        }
        //第一次循环node为null,在这里进行实例化为独占结点
        if (node == null) {
    
                     
            if (shared)
                node = new SharedNode();
            else
                node = new ExclusiveNode();
        //第二次循环node != null, pred = null,初始化头结点,尾结点,这时候头结点和尾结点指向的是同一个结点
        //第三次循环node != null, pred = null,重新设置尾结点,将node变量结点设置为尾结点,前尾结点是node变量结点的前驱节点,通过setPrevRelaxed设置。由于第二次循环后头尾结点指向相同的结点,所以这时候node结点的prev结点和head结点指向相同的结点,即node.prev = head
        //第四次循环node != null, pred != null,node设置为等待(WAITING)状态
        //第五次循环
        } else if (pred == null) {
    
    
            //node结点的等待线程设置为当前线程
            node.waiter = current;
            //获取队列尾结点
            Node t = tail;
            //设置node的prev结点是尾结点
            node.setPrevRelaxed(t);         
            //尾结点是空,初始化头结点。
            if (t == null)
                tryInitializeHead();
            //cas设置尾结点为node结点    
            else if (!casTail(t, node))
                //如果设置尾结点失败,将node的prev结点设置为null
                node.setPrevRelaxed(null);  // back out
            else
                //设置尾结点成功,将上一个尾结点的next结点设置为当前尾结点。
                t.next = node;
        } else if (first && spins != 0) {
    
    
            --spins;                        // reduce unfairness on rewaits
            Thread.onSpinWait();
        //第四次循环:将node结点状态设置为等待(WAITING)状态    
        } else if (node.status == 0) {
    
    
            node.status = WAITING;          // enable signal and recheck
        //第五次循环:调用LockSupport.part方法堵塞线程    
        } else {
    
    
            long nanos;
            spins = postSpins = (byte)((postSpins << 1) | 1);
            if (!timed)
                LockSupport.park(this);
            else if ((nanos = time - System.nanoTime()) > 0L)
                LockSupport.parkNanos(this, nanos);
            else
                break;
            node.clearStatus();
            if ((interrupted |= Thread.interrupted()) && interruptible)
                break;
        }
    }
    return cancelAcquire(node, interrupted, interruptible);
}


 private void tryInitializeHead() {
    
    
    //实例化一个独占结点
    Node h = new ExclusiveNode();
    //将头结点设置为这个独占结点,并设置尾结点
    if (U.compareAndSetReference(this, HEAD, null, h))
        tail = h;
}

unlock()

释放锁

//ReentrantLock.unlock()方法
public void unlock() {
    
    
    //调用AbstractQueuedSynchronizer.release()方法
    sync.release(1);
}
//以独占方式释放锁,arg表示释放的线程数量
public final boolean release(int arg) {
    
    
    //判断当前线程是否已经释放锁(包括锁重入释放)
    if (tryRelease(arg)) {
    
    
        //唤醒队列的第一个线程
        signalNext(head);
        return true;
    }
    return false;
}

ReentrantLock抽象静态内部类Sync,重写了AbstractQueuedSynchronizer的tryRelease()方法。

protected final boolean tryRelease(int releases) {
    
    
    //getState()方法获取state变量的值,因为ReentrantLock是锁是可重入的,这里需要判断重入释放次数
    int c = getState() - releases;
    //判断持有锁的线程是否是当前线程,如果不是,抛出IllegalMonitorStateException。
    if (getExclusiveOwnerThread() != Thread.currentThread())
        throw new IllegalMonitorStateException();
    //如果c的值为0,设置空闲状态为true, 表示当前线程已经不再要占用这个锁了。    
    boolean free = (c == 0);
    //如果锁处于空闲状态,设置锁持有者为null。
    if (free)
        setExclusiveOwnerThread(null);
    //重新设置state变量的值    
    setState(c);
    return free;
}
//唤醒下一个线程
private static void signalNext(Node h) {
    
    
    Node s;
    //如果参数h结点不为空,后继结点也不会空,状态不等于0。取消等待状态,调用unpark唤醒后继节点保存的线程
    if (h != null && (s = h.next) != null && s.status != 0) {
    
    
        //取消等待状态
        s.getAndUnsetStatus(WAITING);
        //s.waiter是后继结点保存的线程,unpack会取消线程的阻塞状态
        LockSupport.unpark(s.waiter);
    }
}

参考

LockSupport中的park与unpark原理
为什么有Synchronized还要ReentrantLock?

猜你喜欢

转载自blog.csdn.net/u012734723/article/details/112058757