ReentrantLock源码

默认是非公平,可以通过构造函数控制公平和非公平

    public ReentrantLock() {
        sync = new NonfairSync();
    }
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

在ReentrantLock中,state可以用来表示该锁被线程重入的次数。当state为0表示该锁不被任何线程持有;当state为1表示线程恰好持有该锁1次(未重入);当state大于1则表示锁被线程重入state次。

非公平锁

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
        final void lock() {
        	// 以cas方式尝试将AQS中的state从0更新为1
            if (compareAndSetState(0, 1))
            	// //获取锁成功则将当前线程标记为持有锁的线程,然后直接返回
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
		// ReentrantLock#NonfairSync重写AbstractQueuedSynchronizer中地tryAcquire方法
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

ReentrantLock.Sync类nonfairTryAcquire方法(真正尝试获取锁地方法)

        final boolean nonfairTryAcquire(int acquires) {
        	// 当前线程
            final Thread current = Thread.currentThread();
            // 获取锁地冲入次数
            int c = getState();
            if (c == 0) {
            	// state为0,说明当前锁未被任何线程持有
                if (compareAndSetState(0, acquires)) {
                	// 加锁成功,把当前线程设为锁的持有者,在获取前可用于判断是否是重入。
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
            	// 锁被占用且当前线程是锁的持有者,说明是重入。
            	// 重入次数+1
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                 // 锁被持有的情况下,只有持有者才能更新锁保护的资源,所以不需要CAS
                setState(nextc);
                return true;
            }
            return false;
        }

ReentrantLock.Sync类tryRelease方法,重写AbstractQueuedSynchronizer中地tryRelease方法

        protected final boolean tryRelease(int releases) {
        	// 当先线程地重入次数-1
            int c = getState() - releases;
            // 只有锁的持有者才能释放锁
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            // 如果当前线程的同步状态为0										
            if (c == 0) {
            	// 锁重入计数减到0,需要真正释放锁了。
                free = true;
                // 如果c为0,写操作完成后,其他线程就会看到锁被释放了,所以setExclusiveOwnerThread必须在这个写之前完成
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

公平锁

首先判断当前AQS的state是否等于0,锁是否被占用,如果没有被占用的话,继续判断队列中是否有排在前面的线程在等待锁,没有的话就修改statte状态,然后将当前线程记录为独占锁的线程,继续判断当前线程是否为独断锁的线程,ReentrantLock是可冲入的,线程可以不停地Lock来增加state的值,对应的需要unlock来解锁,减少state的值,如果上面的条件判断失败,即获取锁失败,则将线程加入到等待线程队列队尾,然后阻塞线程,等待被唤醒

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

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

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
            	// hasQueuedPredecessors 返回false,表示不需要排队
                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;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值