锁系列文章:
java多线程系列7-AbstractQueuedSynchronizer源码分析
java多线程系列8-ReentrantLock源码分析
java多线程系列10-读写锁ReentrantReadWriteLock源码分析
1.Semaphore介绍
Semaphore其实在前面并发工具类中介绍过。Semaphore初始化时会设值许可证的数量,即state的值。当有个线程尝试获取锁时,会尝试更新state的值,一般是将state的值减一。如果成功,则获得锁成功。如果state的值减到0时,后续线程获得锁将会加入队列等待。
Semaphore也会分为公平锁和非公平锁。
先看下构造方法:
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
2.非公平锁
有了前面AQS和ReentrantLock源码分析的基础,再看Semaphore已经简单很多,这里挑重点方法分析下。
(1)acquire方法
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
(2)acquireSharedInterruptibly是AQS中方法
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
(3)tryAcquireShared方法
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
(4)nonfairTryAcquireShared
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//得到state值
int available = getState();
//获得剩余许可证的值
int remaining = available - acquires;
//剩余许可证为负数,返回后加入同步队列
//如果许可证大于0,重置state值
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
3.公平锁
公平锁和上一篇分析的类似,都是先判断队列中是否已有线程在等待,有的话加入等待队列,没有的话和非公平锁一样
(1)tryAcquireShared
protected int tryAcquireShared(int acquires) {
for (;;) {
//判断队列中是否有等待线程
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
4.释放锁
释放锁很简单,就是将许可证增加。
(1)tryReleaseShared
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
if (compareAndSetState(current, next))
return true;
}
}