Java并发之lock源码分析

Java并发之lock源码分析

程序员自己管理锁的释放

lock()方法

      final void lock() {
          //判断当前锁的状态,即STATE的是否为0,如果是0的话就将state改为1,表示当前锁空闲,当前线程抢占成功
            if (compareAndSetState(0, 1))
                //将当前线程记录
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //如果STATE不是0,代表此时锁还在被占用
                //调用acquire(1);方法
                acquire(1);
        }

acquire(1)方法

//该方法进行了tryAcquire(arg)以及acquireQueued(addWaiter(Node.EXCLUSIVE), arg)判断
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

nonfairTryAcquire(1)方法

/**
线程掉用该方法时有3三种情况
1、当前锁没有被线程占用,当前线程获得锁资源,返回true
2、当前锁被线程占用,并且当前线程刚好是占用锁的那个线程,即锁的重入,会将state+1,并且返回true
3、锁被占用,并且不是当前线程占用的,就返回false
*/

final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
        	//得到当前锁的State
            int c = getState();
        //判断state是否为0
            if (c == 0) {
                //如果是0就尝试抢占
                if (compareAndSetState(0, acquires)) {
                    //抢占成功就返回true
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
      		//state不为0,以为当前锁是被占用的
        	//判断当前线程是否是已经获得锁的线程
            else if (current == getExclusiveOwnerThread()) {
                //如果是就把state加上1,并且当此时state+1的结果超出了state的最大正整数会抛出异常
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                //设置state
                setState(nextc);
                return true;
            }
            return false;
        }

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

  • addWaiter(Node.EXCLUSIVE)方法
/**
	将最新线程的NOde加入到等待队列中去
*/
private Node addWaiter(Node mode) {
        //新建一个节点,节点中的Thread为当前线程,模式为排他模式,即排他锁
        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;
           //AQS原子性的设置新的尾结点
            if (compareAndSetTail(pred, node)) {
       			构建好双向链表
                pred.next = node;
                return node;
            }
        }
        //第一次会初始化head、tail并且赋值为空,再新建一个空的节点作为头
        enq(node);
        return node;
    }

acquireQueued(final Node node, int arg)

/**
	调用该方法的前提是,当前线程没有获得锁,并且已经将该线程防放置到等待队列里面自旋,知道等到自己获得锁才会出来
*/
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)) {
                    //是头结点并且获得了锁
                    //释放等待队列中,并且返回一个FALSE
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //判断线程是否需要中断
                //shouldParkAfterFailedAcquire()方法返回值有两种可能
                //true 如果当前的prev的waitstatus为0就返回true
                //false 如果当前prev的waitstatus不为0就循环遍历去除不需要等待的线程节点
                //AQS将节点的waitstatus变成signel
                //如果返回true会将线程挂起处于阻塞状态
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

unlock()方法

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(int releases)

/**
尝试断开锁,放回true就是锁释放成功,否则就返回false
*/
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);
            }
    		//更新将state
            setState(c);
            return free;
        }

unparkSuccessor(Node node)

   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)
            //将waitStatus更新为0
            compareAndSetWaitStatus(node, 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;
       //去死皮,从尾结点遍历,防止线程节点插入式破坏链表结构
        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);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值