美文网首页
juc2-locks-ReentrantLock

juc2-locks-ReentrantLock

作者: modou1618 | 来源:发表于2019-02-03 07:29 被阅读0次
    • 可重入锁,即线程可重复多次获取锁
    • 独占锁

    一 Sync

    • sync继承AbstractQueuedSynchronizer类,实现锁的控制
      private final Sync sync;
    • 独占锁,所以无需实现AbstractQueuedSynchronizer的共享锁的接口
    • 子类NonfairSync是非公平锁,后请求锁的线程可能先获取到锁
    • 子类FairSync是公平锁,按请求锁的先后顺序获取锁
    • 抽象获取锁接口,子类实现。abstract void lock();
    • 非公平尝试锁获取
    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {//没有线程获取锁,cas方式修改锁状态,获取锁
            if (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;
    }
    
    • 锁释放
    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;
    }
    
    • 其他函数
    //当前线程是否占有锁
    protected final boolean isHeldExclusively() {
        return getExclusiveOwnerThread() == Thread.currentThread();
    }
    //获取条件对象
    final ConditionObject newCondition() {
        return new ConditionObject();
    }
    
    //获取占有锁的线程,锁状态为0则没有线程占有锁。
    final Thread getOwner() {
        return getState() == 0 ? null : getExclusiveOwnerThread();
    }
    
    //当前线程获取锁的数量
    final int getHoldCount() {
        return isHeldExclusively() ? getState() : 0;
    }
    //锁状态为0表示没有线程占有锁,非0则表示有线程获取到锁了
    final boolean isLocked() {
        return getState() != 0;
    }
    

    1.1 非公平锁实现NonfairSync

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
    
        /**
         * 在放入等待锁队列之前,即使队列中有线程等待锁,也会两次尝试获取锁。若获取成功,实际上对等待锁队列中的线程来说是非公平的。
         */
        final void lock() {
             //修改锁状态,尝试获取锁
            if (compareAndSetState(0, 1))
               //成功则修改锁的线程信息
                setExclusiveOwnerThread(Thread.currentThread());
            else
            /*
            * 修改锁状态失败则尝试获取锁一次,
            * 先调用tryAcquire尝试获取锁,
            * 失败则加入等待锁队列中,队列中线程按先后顺序获取锁
             */
                acquire(1);
        }
    
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
    

    1.2 公平获取锁FairSync

    • 获取锁的线程先放入等待锁队列中,然后再按队列节点顺序获取锁。即按等待时间长短公平获取。
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
    
        final void lock() {
            acquire(1);
        }
    
        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;
        }
    }
    

    二 ReentrantLock接口

    • 默认使用非公平锁,也可通过构造函数参数指定使用公平锁
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    
    public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
    }
    
    • 加锁
    public void lock() {
        sync.lock();//非中断加锁,失败则等待
    }
    
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);//可中断加锁,失败则等待
    }
    
    public boolean tryLock() {//尝试非中断加锁,失败则返回false
        return sync.nonfairTryAcquire(1);
    }
    
    //加锁,最长等待timeout时间,可中断。超时加锁失败则返回false
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
    
    • 释放锁
    public void unlock() {
        sync.release(1);
    }
    

    相关文章

      网友评论

          本文标题:juc2-locks-ReentrantLock

          本文链接:https://www.haomeiwen.com/subject/miessqtx.html