美文网首页程序员
四.AQS的实现

四.AQS的实现

作者: 蜗牛1991 | 来源:发表于2017-09-18 11:32 被阅读0次

    一.ReentrantLock

    • 层次图
      • ReentrantLock是独占模式,其中NonfairSync 是非公平锁,FairSync是公平锁,构造器就是构造它们,Sync定义抽象Lock方法供子类实现,unlock方法就是state减一。
    public class ReentrantLock implements Lock, java.io.Serializable {
        public ReentrantLock() {  sync = new NonfairSync(); }
        public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
        private final Sync sync;
        abstract static class Sync extends AbstractQueuedSynchronizer { abstract void lock();}
        static final class NonfairSync extends Sync { }
        static final class FairSync extends Sync { }
       public void unlock() {sync.release(1);  }
    }
    
    • 公平锁的实现
      • 回想一下上节获取锁流程(Acquire):试图获取锁(tryAcquire)若失败,则进入acquireQueued方法获取阻塞队列
      • ReentrantLock获取锁方式:当state=1,若当前节点不是头结点且是阻塞队列第一个节点,并通过CAS将state值+1,阻止其他线程获取;若state!=0且为当前线程是获取锁的线程,则继续讲state+1;其他情况获取锁失败
     static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
            //AQS方法
            final void lock() {
                acquire(1);
            } 
           //AQS tryAcquire方法子类的实现
            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;
            }
        }
    
    • 非公平锁的实现
      • 回想一下上节获取锁流程(Acquire):试图获取锁(tryAcquire)若失败,则进入acquireQueued方法获取阻塞队列
      • ReentrantLock获取锁方式:若state=0,当前线程尝试通过CAS看看能不能把state从0变为1(即获取锁),如果可以的话,直接获取锁而不需要排队(按队列顺序)
     static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            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;
            }
    

    二.信号量Semaphore实现原理

    • 信号量允许多条线程获取锁,它的锁是一种共享锁,信号量也有公平模式与非公平模式,与ReentrantLock类似
    • 实现方式
    • 通过设置permits(允许几个线程)作为初始state,没获取一次state-1,,如果返回的是一个<0的数字,那么构建FIFO队列,线程阻塞,直到前面的执行完才能唤醒后面的。
      FairSync(int permits) {
                super(permits);
            }
    
            protected int tryAcquireShared(int acquires) {
                for (;;) {
                    if (hasQueuedPredecessors())
                        return -1;
                    int available = getState();
                    int remaining = available - acquires;
                    if (remaining < 0 ||
                        compareAndSetState(available, remaining))
                        return remaining;
                }
            }
    

    三.CountDownLatch实现原理

    • 传入一个count作为初始state,await的时候判断是不是0,是0返回1表示成功,返回-1表示失败,构建FIFO队列,head头只连接一个Node,Node中的线程就是调用CountDownLatch的await()方法的线程,每次countDown的时候对state-1,直到state减到0的时候才算tryReleaseShared成功,tryReleaseShared成功,唤醒被挂起的线程
       private static final class Sync extends AbstractQueuedSynchronizer {
            Sync(int count) {
                setState(count);
            }
    
            int getCount() {
                return getState();
            }
    
            protected int tryAcquireShared(int acquires) {
                return (getState() == 0) ? 1 : -1;
            }
    
            protected boolean tryReleaseShared(int releases) {
                // Decrement count; signal when transition to zero
                for (;;) {
                    int c = getState();
                    if (c == 0)
                        return false;
                    int nextc = c-1;
                    if (compareAndSetState(c, nextc))
                        return nextc == 0;
                }
            }
        }
    

    四.ThreadPoolExecutor的实现

    相关文章

      网友评论

        本文标题:四.AQS的实现

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