码迷,mamicode.com
首页 > 其他好文 > 详细

分析NonfairSync加锁/解锁过程

时间:2016-07-01 18:24:52      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

类继承关系:

NonfairSync => Sync => AbstractQueuedSynchronizer

 

类NonfairSync

final void lock() {

    if (compareAndSetState(0, 1))

        setExclusiveOwnerThread(Thread.currentThread());

    else

        acquire(1);

}

分析:

compareAndSetState(0, 1):通过cas操作更新state状态,若成功,则获取到锁,否则,进行排队申请操作acquire

类AbstractQueuedSynchronizer

public final void acquire(int arg) {

    if (!tryAcquire(arg) &&

        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

        selfInterrupt();

}

分析:

tryAcquire方法最终实现为:

类Sync

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;

}

通过cas操作更新state状态,若成功,则获取到锁,否则,首先进行排队,

类AbstractQueuedSynchronizer

private Node addWaiter(Node mode) {

    Node node = new Node(Thread.currentThread(), mode);

    // Try the fast path of enq; backup to full enq on failure

    Node pred = tail;

    if (pred != null) {

        node.prev = pred;

        if (compareAndSetTail(pred, node)) {

            pred.next = node;

            return node;

        }

    }

    enq(node);

    return node;

}

注意:

每一个线程被封装成一个Node节点。

进入enq方法——入队列

private Node enq(final Node node) {

    for (;;) {

        Node t = tail;

        if (t == null) { // Must initialize

            if (compareAndSetHead(new Node()))

                tail = head;

        } else {

            node.prev = t;

            if (compareAndSetTail(t, node)) {

                t.next = node;

                return t;

            }

        }

    }

}

分析:

这里针对head和tail属性的赋值均为cas原子操作。

最终模型如图:

 技术分享

如果多线程并发入队,最终结果如图:

 技术分享

注:prev和next分别为Node类的两个属性

入队操作结束后,开始请求队列acquireQueued

类AbstractQueuedSynchronizer

final boolean acquireQueued(final Node node, int arg) {

    boolean failed = true;

    try {

        boolean interrupted = false;

        for (;;) {

            final Node p = node.predecessor();

            if (p == head && tryAcquire(arg)) {

                setHead(node);

                p.next = null; // help GC

                failed = false;

                return interrupted;

            }

            if (shouldParkAfterFailedAcquire(p, node) &&

                parkAndCheckInterrupt())

                interrupted = true;

        }

    } finally {

        if (failed)

            cancelAcquire(node);

    }

}

分析:

  1. Node p = node.predecessor()获取node的prev节点
  2. 如果prev==head节点并且tryAcquire返回true,则更新head节点为当前节点,并退出循环,也就获取到了锁。
  3. 否则的话,执行shouldParkAfterFailedAcquire和parkAndCheckInterrupt。
  4. setHead方法来修改head属性,改变队列的头部节点

  其中,shouldParkAfterFailedAcquire方法是针对waitStatus属性的修改

  private final boolean parkAndCheckInterrupt() {

      LockSupport.park(this);

      return Thread.interrupted();

  }

  LockSupport.park(this),使当前线程进入阻塞。

技术分享

 

unlock分析

类AbstractQueuedSynchronizer

public final boolean release(int arg) {

    if (tryRelease(arg)) {

        Node h = head;

        if (h != null && h.waitStatus != 0)

            unparkSuccessor(h);

        return true;

    }

    return false;

}

类Sync

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);

    }

    setState(c);

    return free;

}

分析:

主要工作就是设置还原state状态

类AbstractQueuedSynchronizer

private void unparkSuccessor(Node node) {

    int ws = node.waitStatus;

    if (ws < 0)

        compareAndSetWaitStatus(node, ws, 0);

    Node s = node.next;

    if (s == null || s.waitStatus > 0) {

        s = null;

        for (Node t = tail; t != null && t != node; t = t.prev)

            if (t.waitStatus <= 0)

                s = t;

    }

    if (s != null)

        LockSupport.unpark(s.thread);

}

分析:

  1. 入参node即head节点
  2. Node s = node.next;即获取到下一个节点,即正在阻塞中的线程
  3. LockSupport.unpark(s.thread);即激活线程

分析NonfairSync加锁/解锁过程

标签:

原文地址:http://www.cnblogs.com/liuxinan/p/5633879.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!