lock看上去很牛,其实真的很牛,如果你仔细研究代码发现,所以的lock都只是去争一个变量state
private volatile int state;
如果你能将这个state从零变成1,你就可以获得资源,
因为要判断是谁获得了这个state,所以需要保留这个线程的对象。
因为要记录有哪些线程在争论lock,所以需要队列,既然有队列,就有队列的机制,公平机制(先到先得),非公平机制(可能存在饿死的线程,一直得不到)。这里的队列是用Node组成的链表,记录了head和tail。
源码:
public ReentrantLock() { sync = new NonfairSync(); }
默认采用非公平的机制。
对比公平和非公平:
非公平的lock 直接先去尝试获取一次线程,如果拿不到再去排队。
final void lock() {
//这里就是上面说的争的对象。
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
公平的,会直接去排队。
final void lock() {
acquire(1);
}
公平的申请:
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;
}
世事可能不如意,所以需要排队。在末尾添加。
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;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
排队的用户怎么执行能,肯定在循环中,
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
到此结束。
问题:每个Node都有一个State吗?还是共用的呢。