Java系列之ReentrantLock

1. ReentrantLock可重入锁分为公平和非公平锁,通过构造函数进行设置,有时会用它来替代synchronized,区别在于前者能实现顺序公平,实现方式通过原子cas操作即cpu原语实现,而后者是通过字节码monitor-enter以及monitor-exit实现,

 public ReentrantLock() {
        sync = new NonfairSync();
    }

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

2. 获取锁,以及两种锁不同的实现,NonfairSync会先通过cas操作设置状态,失败后才会执行父类操作

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

// 非公平锁
final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

// 公平锁
final void lock() {
            acquire(1);
        }

父类通过tryAcquire操作尝试获取锁,失败后会把该线程加入到等待队列中。

 public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

NonfairSync实现如下,先通过状态判断当前锁是否被强占,如果没的话就会通过cas操作抢占锁并且设置本线程为当前锁的持有线程,如果状态不为0即代表当前锁已经被强占,通过判断持有锁的线程是否为本线程来进行后续操作,如果为本线程的话就为状态加一,也是为了后续的每次释放减去相应的一,用来实现可重入。

protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }

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

FairSync的实现就是增加一个前置条件,当没有线程持有锁时判断锁的等待队列中是否有其他线程,以此来实现公平锁。

 protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                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;
        }

3. 可被中断的获取锁,会抛出InterruptedException异常。其他的和不可中断获取操作类似。

public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (!tryAcquire(arg))
            doAcquireInterruptibly(arg);
    }

4. 尝试获取锁直接通过cas操作获取锁,或者判断当前持有锁的线程是否为本线程,快速响应。

 public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

5. 带有等待时间的尝试获取锁,成功则获取,失败则进入等待队列中直到限时停止。

 public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquire(arg) ||
            doAcquireNanos(arg, nanosTimeout);
    }

6. 释放锁,判断持有锁的线程是否为本线程,不是则抛出异常,否则针对状态减去对应的数量一,重入锁的释放需要执行多次该操作,直到改状态为0才可以判断锁已经被本线程释放,删除锁的持有线程,才可以通过LockSupport.unpark操作通知其他线程获取锁,之前获取锁未成功的线程都被LockSupport.park所暂停。

 public void unlock() {
        sync.release(1);
    }

public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return 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);
            }
            setState(c);
            return free;
        }

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值