展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

锁(二):ReentrantLock源码之非公平锁的实现

  • 代码案例
public class ReentrantLockDemo {

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        reentrantLock.lock();
        reentrantLock.unlock();
    }

}
  • 查看无参构造方法
    public ReentrantLock() {
        sync = new NonfairSync();    // new了1个非公平实现
    }
  • 查看sync

  • 查看有参构造

    public ReentrantLock(boolean fair) {      // 传入boolean类型的参数
        sync = fair ? new FairSync() : new NonfairSync();    // 为true时返回公平实现,否则返回非公平实现
    }

  • ReentrantLock实现了Lock接口

  • 查看方法

  • 查看内部类

  • 查看lock方法

public class ReentrantLockDemo {

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        reentrantLock.lock();
        reentrantLock.unlock();
    }

}
  • ctrl查看lock方法

  • 查看非公平实现

  • if操作是将当前线程设置为持有锁线程,如果失败了则执行sync.acquire(1);

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

public final void acquire(int arg) {
    // 尝试获取锁
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))    // 同时获取队列失败
        selfInterrupt();      // 则线程终止
}
  • 查看尝试获取锁的方法
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }
  • 查看非公平实现
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);        // 非公平的尝试获取
    }
}

# ctrl继续查看
@ReservedStackAccess
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;    // 重入状态加1
        if (nextc < 0) // overflow      // 超过最大重入状态,抛出异常
            throw new Error("Maximum lock count exceeded");
        setState(nextc);    // 更新
        return true;    // 获得锁
    }
    return false;
}
  • 查看addWaiter方法
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
  • 查看EXCLUSIVE

  • 查看addWaiter方法

    private Node addWaiter(Node mode) {
        Node node = new Node(mode);    // 传入参数,当前线程,new1个Node

        for (;;) {
            Node oldTail = tail;    
            if (oldTail != null) {
                node.setPrevRelaxed(oldTail);
                if (compareAndSetTail(oldTail, node)) {    
                    oldTail.next = node;
                    return node;
                }
            } else {
                initializeSyncQueue();    
            }
        }
    }
  • 查看Node
Node(Node nextWaiter) {
    this.nextWaiter = nextWaiter;
    THREAD.set(this, Thread.currentThread());
}
  • 继续查看addWaiter方法
    private Node addWaiter(Node mode) {
        Node node = new Node(mode);    // 传入参数,当前线程,new1个Node

        for (;;) {
            Node oldTail = tail;    // 前置节点指向尾节点
            if (oldTail != null) {
                node.setPrevRelaxed(oldTail);
                if (compareAndSetTail(oldTail, node)) {    // node设置为尾节点
                    oldTail.next = node;      // 尾节点的下一个节点,指向node
                    return node;      // 返回node
                }
            } else {
                initializeSyncQueue();    // 若整条队列为null,执行入队
            }
        }
    }
  • 查看acquireQueued方法
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

# ctrl查看
    final boolean acquireQueued(final Node node, int arg) {
        boolean interrupted = false;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {    // 前置节点如果是头节点,同时尝试获取锁
                    setHead(node);    // 当前节点设置为头节点
                    p.next = null; // help GC    将原本的头节点移除
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node))    // 失败时,挂起
                    interrupted |= parkAndCheckInterrupt();
            }
        } catch (Throwable t) {
            cancelAcquire(node);
            if (interrupted)
                selfInterrupt();
            throw t;
        }
    }
  • 查看predecessor,返回前置节点
        final Node predecessor() {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }
  • 查看shouldParkAfterFailedAcquire方法
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */
            return true;
        if (ws > 0) {
            /*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             */
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */
            pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
        }
        return false;
    }
  • 查看waitStatus
Status field, taking on only the values: 
SIGNAL: The successor of this node is (or will soon be) blocked (via park), so the current node must unpark its successor when it releases or cancels. To avoid races, acquire methods must first indicate they need a signal, then retry the atomic acquire, and then, on failure, block. 
CANCELLED: This node is cancelled due to timeout or interrupt. Nodes never leave this state. In particular, a thread with cancelled node never again blocks. 
CONDITION: This node is currently on a condition queue. It will not be used as a sync queue node until transferred, at which time the status will be set to 0. (Use of this value here has nothing to do with the other uses of the field, but simplifies mechanics.) PROPAGATE: A releaseShared should be propagated to other nodes. This is set (for head node only) in doReleaseShared to ensure propagation continues, even if other operations have since intervened. 0: None of the above The values are arranged numerically to simplify use. Non-negative values mean that a node doesn't need to signal. So, most code doesn't need to check for particular values, just for sign. The field is initialized to 0 for normal sync nodes, and CONDITION for condition nodes. It is modified using CAS (or when possible, unconditional volatile writes).

# ctrl + shift + y 翻译后,如下几种状态
状态字段,仅取值: 
SIGNAL:此节点的后继节点已(或即将)被阻塞(通过停放),因此当前节点在释放或取消时必须取消停放其后继节点。为了避免竞争,获取方法必须首先表明它们需要一个信号,然后重试原子获取,然后在失败时阻塞。 
CANCELLED:该节点由于超时或中断而被取消。节点永远不会离开这个状态。特别是,具有取消节点的线程永远不会再次阻塞。 
CONDITION:此节点当前位于条件队列中。在传输之前不会用作同步队列节点,此时状态将设置为 0。(此处使用此值与该字段的其他用途无关,但简化了机制。)传播:A releaseShared 应该传播到其他节点。这是在 doReleaseShared 中设置的(仅针对头节点),以确保传播继续进行,即使其他操作已经介入。 0:以上都不是 这些值以数字排列以简化使用。非负值意味着节点不需要发出信号。因此,大多数代码不需要检查特定值,只需检查符号即可。对于正常同步节点,该字段初始化为 0,对于条件节点,该字段初始化为 CONDITION。它使用 CAS 进行修改(或者在可能的情况下,无条件的 volatile 写入)。

volatile int waitStatus;
  • 查看释放锁的操作
public class ReentrantLockDemo {

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        reentrantLock.lock();
        reentrantLock.unlock();
    }

}

# ctrl
    public void unlock() {
        sync.release(1);
    }
  • 查看release方法
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
  • 查看tryRelease方法
    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }
  • 查看实现类
        @ReservedStackAccess
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())    // 当前锁的线程不是持有锁的线程
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);    // 当前持有锁的线程设置为null
            }
            setState(c);
            return free;
        }
  • 查看unparkSuccessor方法
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

# ctrl
    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;    // 如果这个节点是等待状态
        if (ws < 0)
            node.compareAndSetWaitStatus(ws, 0);

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        Node s = node.next;    // 头节点的下一个节点赋值给s
        if (s == null || s.waitStatus > 0) {    // 如果该节点为null,且waitStatus 状态>0
            s = null;
            for (Node p = tail; p != node && p != null; p = p.prev)    // 从尾部开始遍历链表
                if (p.waitStatus <= 0)
                    s = p;
        }
        if (s != null)
            LockSupport.unpark(s.thread);
    }
posted @ 2022-05-14 10:47  DogLeftover  阅读(18)  评论(0编辑  收藏  举报