//默认是非公平锁 true是公平锁,false是非公平锁
ReentrantLock reentrantLock = new ReentrantLock();
state为什么是voliate修饰
volatile + CAS实现非阻塞式线程同步:通过Syncronized的方式当然可以实现线程同步,但是消耗太大;AQS框架使用volatile + CAS实现非阻塞式线程同步,线程同步需要保证3个方面:可见性、有序性、原子性,volatile保证了变量的可见性和有序性,用CAS操作保证变量的原子性。
一、非公平锁(NonfairSync)
1、lock()
final void lock() {
//如果当前没没有线程拿到锁,给当前线程加锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
//如果已经有线程获得锁
else
acquire(1);
}
2、acquire(1)
public final void acquire(int arg) {
//尝试获取锁 添加等待线程
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
3、tryAcquire(arg)
作用:获取锁,同时包含记录重入锁
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//当前线程拿到锁了
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//重入锁:已经有线程拿到锁,并且是当前线程,state++
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;
}
4、addWaiter(Node mode)
双向链表,添加等待的线程,head<=>node<=>tail
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
//从第二个开始的线程,移动tail指向当前线程
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//第一个线程,head(new Node())<=>tail(node第一个线程)
enq(node);
return node;
}
5、enq(node)
第一个线程添加到双向链表
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
6、acquireQueued(final Node node, int arg)
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
//检查双向链表的第一个node是否获得锁
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
//waitStatus,等待状态默认是0,把双向链表的当前节点之前的节点状态更新成-1,等待解除阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
//阻塞当前线程
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
7、unlock
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
//释放后继者
unparkSuccessor(h);
return true;
}
return false;
}
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
二、公平锁
公平锁和非公平锁的区别就是,非公平锁首先还尝试获取锁,公平锁直接阻塞,以下代码:
final void lock() {
acquire(1);
}