需要有一定的JUC基础
公平锁与非公平锁
公平锁:
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;
}
非公平锁:
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;
}
通过代码的对比可以发现公平锁中多了!hasQueuedPredecessors()这一行代码:
我们继续看源码:
public final boolean hasQueuedPredecessors() {
Node h, s;
if ((h = head) != null) {
if ((s = h.next) == null || s.waitStatus > 0) {
s = null; // traverse in case of concurrent cancellation
//从后往前找
for (Node p = tail; p != h && p != null; p = p.prev) {
if (p.waitStatus <= 0)
s = p;
}
}
if (s != null && s.thread != Thread.currentThread())
return true;
}
return false;
}
该方法会先看是否有队列,也就是head是否为null,有队列则排队。不公平,会直接抢占一次试试。
如果是重入的话,会看第一个有效节点是不是自己。
可重入和不可重入
可重入:
nonfairTryAcquire方法中
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
tryRelease方法中
int c = getState() - releases;
// 当前线程不是持有锁的线程,抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 如果持有线程全部释放,将当前独占锁所有线程设置为null,并更新state
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
不可重入:
protected boolean tryAcquire(int acquires) {
if (this.compareAndSetState(expect:0, _update:1)){
this.owner = Thread.currentThread();
return true;
}else{
return false;
}
}
protected boolean tryRelease(int releases) {
if (Thread.currentThread() != this.owner) {
throw new IllegalMonitorStateException();
} else {
this.owner = null;
this.setState(0);
return true;
}
}
只有0和1并不会进行相加减操作。失败后阻塞。
独享锁和共享锁
基本常识:有共享锁的情况下,不能添加独享锁;有独享锁的情况下,不能添加共享锁。有独享锁的情况下,不可以添加另一把读享锁。有共享锁的情况下,可以添加另一把共享锁。
该类锁的state©的结构是
高16位读锁的个数,第十六位代表写锁的个数
w = exclusiveCount(c) //取低16位的最大值与当前的c做与运算,获取写锁
独享锁
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState(); // 取到当前锁的个数
int w = exclusiveCount(c); // 取写锁的个数w
if (c != 0) {
if (w == 0 || current != getExclusiveOwnerThread()) // 如果c!=0,w=0,则代表有读锁。
return false;
if (w + exclusiveCount(acquires) > MAX_COUNT) // 如果写入锁的数量大于最大数(65535,2的16次方-1)就抛出一个Error。
throw new Error("Maximum lock count exceeded");
setState(c + acquires);
return true;
}
if (writerShouldBlock() || !compareAndSetState(c, c + acquires)) // 如果当且写线程数为0,并且当前线程需要阻塞那么就返回失败;或者如果通过CAS增加写线程数失败也返回失败。
return false;
setExclusiveOwnerThread(current); // 如果c=0,w=0或者c>0,w>0(重入),则设置当前线程或锁的拥有者
return true;
}
共享锁
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
//如果有独享锁,则失败
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c);
//如果不需要阻塞,且小于最大数,并通过CAS更新成功,则过的读锁
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
return 1;
}
return fullTryAcquireShared(current);
}