Semaphore 代码执行的流程,分析acquire的过程
信号量在多线程中有着重要的应用,它的原理是将资源抽象成信号量,如果信号量大于0表明有可用资源,小于0,则需要等待。
对应申请时,就是做信号量减操作;
对应释放时,就是做信号量加操作。
资源又抽象成state,这是个所有线程都可见的变量。通过state就可以判断线程是不是可以访问共享资源了。
1.new Semaphore()对象时,它调用的 sync = new NonfairSync(permits);可以看出它是调用非公平的同步辅助类,其中sync的类型是Sync,它的定义如下:
abstract static class Sync extends AbstractQueuedSynchronizer{};
2.NonfairSync类又继承Sync类,它具体实现如下:
final static class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
super(permits);
/*此处调用的是Sync(int permits) {
setState(permits);
}
最终state的定义是这样的private volatile int state;
这个state对所有的线程是可见的,并且是最新的值。
*/
}
//这个是在第三步中的acquireSharedInterruptibly()方法被调用
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
3.看看acquire()方法的执行过程
先是调用如下的方法:
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
acquireSharedInterruptibly(1) 这个方法调用下面这个方法:
public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//如果小于0,表明没有资源了,就要进入队列中去
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
4.tryAcquireShared()方法调用nonfairTryAcquireShared()方法,看看它的具体是怎样实现。
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//最新的state值
int available = getState();
//还剩下多少个许可证了(permit)
int remaining = available - acquires;
//只有在还剩有时才更新状态
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
5.如果没有许可证了,就要进入队列中去了,看看doAcquireSharedInterruptibly()这个方法的实现
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
/*
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//进入队列
enq(node);
return node;
}
*/
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
break;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
// Arrive here only if interrupted
cancelAcquire(node);
throw new InterruptedException();
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30024515/viewspace-1431830/,如需转载,请注明出处,否则将追究法律责任。