CAS自旋实现的轻量级锁的两大问题
- CAS空自旋浪费大量CPU资源
- 导致“总线风暴”(大量的cas操作导致总线流量剧增)
关于总线风暴以及总线锁的知识,参考http://t.csdn.cn/3wLCD
解决CAS恶性空自旋有效方式(空间换时间)两种方式

CLH锁的特点:

AQS的特点:
static final class Node {
//表示线程是因为获取共享资源时阻塞,而被添加到队列中的
static final Node SHARED = new Node();
// 表示线程因为获取独占资源时阻塞,而被添加到队列中的。
static final Node EXCLUSIVE = null;
//以下是节点的状态
//取消状态 1
static final int CANCELLED = 1;
//节点等待状态 -1:标识后继线程处于等待状态
static final int SIGNAL = -1;
//节点等待状态 -2:标识当前线程处于条件等待
static final int CONDITION = -2;
//节点等待状态 -3:标识下一次共享锁的acquireShared操作需要无条件传播
static final int PROPAGATE = -3;
//节点状态:Canceled Signal Condition Propagate 0
//普通同步节点的初始值为0,条件等待节点的初始值为-2
volatile int waitStatus;
//前驱节点,当前节点会在前驱节点上自选,检查前驱节点的waitStatus的状态
volatile Node prev;
volatile Node next;
volatile Thread thread;
//如果当前Node不是普通节点,而是条件等待节点,则节点处与某个条件的等待队列上
//此属性指向下一个条件等待节点
Node nextWaiter;
waitStatus属性:
//队头节点
private transient volatile Node head;
//队尾节点
private transient volatile Node tail;
//标记为状态,AQS适用state标识锁的状态
private volatile int state;
//设置同步状态(无法保证原子性)
protected final void setState(int newState) {
state = newState;
}
//通过同步状态(通过CAS保证原子性)
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
ReentrantLock初始化state为0,表示未锁定状态。线程A调用tryAcquire()独占该锁并使其state+1.其他线程对该锁tryAcquire()会失败。直到A线程unlock该锁的state为0(释放锁)。A线程在此过程中,可以重复获取该锁(state累加),累加多少次,就要释放多少次。
AQS继承了AbstractOwnableSynchronizer

public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
/** Use serial ID even though all fields transient. */
private static final long serialVersionUID = 3737899427754241961L;
/**
* Empty constructor for use by subclasses.
*/
protected AbstractOwnableSynchronizer() {
}
/**
* The current owner of exclusive mode synchronization.
独占锁情形下,占用该锁的线程
*/
private