AQS,即AbstractQueuedSynchronizer, 队列同步器,它是多线程访问共享资源的同步器框架,Java中的ReentrantLock/Semaphore/CountDownLatch等同步组件都依赖于它。它维护了一个同步器状态 (volatile int state 代表共享资源)和一个线程等待队列(多线程争用资源被阻塞时会进入此双向队列 ,FIFO )
AQS大致流程,以ReentrantLock为例
这篇讲的比较清楚 https://www.cnblogs.com/fanBlog/p/9336126.html
ReentrantLock 中的公平锁和非公平锁
公平锁能保证:老的线程排队使用锁,新线程仍然排队使用锁。
非公平锁保证:老的线程排队使用锁;但是可能会出现新线程要先于等待队列中的线程抢占到锁
公平锁的实现是每次获取锁的时候会判断等待队列中是否还有线程在等待,而非公平锁就不会判断等待队列中是否还有线程在等待,新来的线程有可能比等待中的线程先抢到锁
公平锁获取锁的方法
/** * 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()保证了不论是新的线程还是已经排队的线程都顺序使用锁 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; }
非公平锁获取锁的方法
/** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ 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; }
什么是CAS
在并发环境下,某个线程对共享变量先进行操作,如果没有其他线程争用共享数据那操作就成功;如果存在数据的争用冲突,那就才去补偿措施,比如不断的重试机制,直到成功为止,因为这种乐观的并发策略不需要把线程挂起,效率要比采用锁的机制高。在硬件指令集的发展驱动下,使得 "操作和冲突检测" 这种看起来需要多次操作的行为只需要一条处理器指令便可以完成,这些指令中就包括非常著名的CAS指令(Compare-And-Swap比较并交换)
public final int incrementAndGet(){ for(;;){ int current=get(); int next=current+1; if(compareAndSet(current,next)){ return next; } } }