b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

semaphore AQS(AbstractQueuedSynchronizer)源代码分析(三)——共享的aquire

电脑杂谈  发布时间:2018-02-13 15:13:49  来源:网络整理

?? ?? ??本文是在AQS(AbstractQueuedSynchronizer)源代码分析(一)和AQS(AbstractQueuedSynchronizer)源代码分析(二)两篇文章的基础上编写的。关于shouldParkAfterFailedAcquire,addWaiter,parkAndCheckInterrupt,park,unpark,unparkSuccessor方法,如果不清楚,可以参考前两篇文章,本文不再做说明。

?? ?? ??AQS中的非共享模式与共享模式的区别在于,非共享模式每次只能有一个线程执行被锁定的内容,即目标语句或者目标方法。semaphore比如ReentrantLock类,在lock方法锁定的范围内,只会同时有一个线程在执行。而共享模式则是可以多个线程同时执行被锁定内容的。典型的应用类就是Semaphore。在设定初始信号量的值之后,比如是5;那么就会有五个线程同时执行。semaphore????

??一、共享的acquire方法

public final void acquireShared(int arg) {
	//这个方法由子类实现。这里使用Semaphore.NonfairSync类中的tryAcquireShared进行说明
	if (tryAcquireShared(arg) < 0) 
	
		//返回值小于0,则表示sate值已经被使用完,即已经有5个线程在运行。其他线程不能再进入了
		doAcquireShared(arg); 
}

//类Semaphore.NonfairSync
protected int tryAcquireShared(int acquires) {
	return nonfairTryAcquireShared(acquires);
}
		
final int nonfairTryAcquireShared(int acquires) {

/**
   *   当使用Semaphore时会有如下的代码:
   *   Semaphore semaphore = new Semaphore(5);
   *   semaphore.acquire();
   *   		……
   *   semaphore.release();
   *   
   *   这里的getSate,如果是第一次进行semaphore.acquire()的话,
   *   getSate返回5,即我们设定的初始值
   *   每一次semaphore.acquire()都会对将getSate的返回值进行减少,
   *   即:int remaining = available - acquires,这段代码的含义
   */
	for (;;) {
		int available = getState(); //获取sate状态
		int remaining = available - acquires; 
		if (remaining < 0 ||
			compareAndSetState(available, remaining))
			return remaining;  //这里会返回本次acquire之后,还剩余的sate值
	}
}

上面的代码演示了Semaphore是如何进行信号量的获取操作的。当信号量获取失败之后,就会执行doAcquireShared(arg)方法。看一下doAcquireShared(arg)方法的代码:

private void doAcquireShared(int arg) {
	final Node node = addWaiter(Node.SHARED); //向队列增加节点,追加的node是共享模式的node
	boolean failed = true;
	try {
		boolean interrupted = false;
		for (;;) {  //死循环
			final Node p = node.predecessor(); //获取当前节点的prevNode
			if (p == head) {
				int r = tryAcquireShared(arg);  //如果是prevNode节点如果是head节点,则再次尝试acquire
				if (r >= 0) { 
					setHeadAndPropagate(node, r); //再次尝试,获取成功
					p.next = null; // help GC
					if (interrupted)
						selfInterrupt();
					failed = false;
					return;
				}
			}
			if (shouldParkAfterFailedAcquire(p, node) && //再次尝试,获取失败,挂起线程。可以参考前两篇文章
				parkAndCheckInterrupt())
				interrupted = true;
		}
	} finally {
		if (failed)
			cancelAcquire(node);
	}
}


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-75627-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    每日福利
    热点图片
    拼命载入中...