1. Semaphore

Semaphore和ReentrantReadWriteLock.ReadLock(读锁)都采用AbstractOwnableSynchronizer共享排队的方式实现。

关于AbstractQueuedSynchronizer中的独占锁和共享锁,请参考ReentrantLock(http://www.cnblogs.com/bjorney/p/8040085.html)和ReentrantReadWriteLock(http://www.cnblogs.com/bjorney/p/8064268.html)

问题:Semaphore在acquire时不检查传入的参数是否超过state最大值??? 例如,new Semaphore(5, ture || false) -> acquire(10),则调用acquire的线程将被阻塞
           1)在公平模式下,之后所有调用acquire的线程都将在SyncQueue中排队而永远阻塞???
           2)在非公平模式下,之后所有acquire失败而参与排队的线程都将永远阻塞???

public class Semaphore implements java.io.Serializable {
private final Sync sync; public Semaphore(int permits) {
sync = new NonfairSync(permits); // 公平竞争,sync的锁状态(锁计数)state = permits
} public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits); // 公平竞争 || 非公平竞争
} public void acquire() throws InterruptedException; // acquire(1)
public void acquire(int permits) throws InterruptedException { // permits必须>=0
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
} public void acquireUninterruptibly(); // acquireUninterruptibly(1)
public void acquireUninterruptibly(int permits) { // permits必须>=0
if (permits < 0) throw new IllegalArgumentException();
sync.acquireShared(permits);
} public boolean tryAcquire(); // tryAcquire(1)
public boolean tryAcquire(int permits) { // permits必须>=0
if (permits < 0) throw new IllegalArgumentException();
return sync.nonfairTryAcquireShared(permits) >= 0;
} public boolean tryAcquire(long timeout, TimeUnit unit); // tryAcquire(1, timeout, unit)
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException { // permits必须>=0
if (permits < 0) throw new IllegalArgumentException();
return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
} public void release(); // release(1)
public void release(int permits) { // permits必须>=0
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
} ... ...
}

2. Semaphore.Sync

abstract static class Sync extends AbstractQueuedSynchronizer {
Sync(int permits) {
setState(permits);
} final int nonfairTryAcquireShared(int acquires) { // 尝试非公平取锁
for (;;) {
// CAS(state)失败将回到此处
int available = getState(); /*记录state*/
int remaining = available - acquires;
if (remaining < 0 || compareAndSetState(available, remaining)) //remaining >= 0时/*CAS设置state -= acquires*/
return remaining; // remaining < 0:SyncQueue中排队
}
} protected final boolean tryReleaseShared(int releases) {
for (;;) {
// CAS(state)失败将回到此处
int current = getState(); /*记录state*/
int next = current + releases;
if (next < current) throw new Error("Maximum permit count exceeded");
if (compareAndSetState(current, next)) /*CAS设置state += releases*/
return true;
}
} ... ...
} static final class NonfairSync extends Sync {
NonfairSync(int permits) {
super(permits);
} protected int tryAcquireShared(int acquires) { // 尝试非公平取锁
return nonfairTryAcquireShared(acquires);
}
} static final class FairSync extends Sync {
FairSync(int permits) {
super(permits);
} protected int tryAcquireShared(int acquires) { // 尝试公平取锁
for (;;) {
// CAS(state)失败将回到此处
if (hasQueuedPredecessors()) // SyncQueue不为空 && SyncQueue中下个待唤醒节点非当前线程所在节点
return -1; //
int available = getState(); /*记录state*/
int remaining = available - acquires;
if (remaining < 0 || compareAndSetState(available, remaining)) //remaining >= 0时/*CAS设置state -= acquires*/
return remaining;
}
}
}

Semaphore(信号量)源码分析的更多相关文章

  1. Java并发编程笔记之Semaphore信号量源码分析

    JUC 中 Semaphore 的使用与原理分析,Semaphore 也是 Java 中的一个同步器,与 CountDownLatch 和 CycleBarrier 不同在于它内部的计数器是递增的,那 ...

  2. Semaphore信号量源码解析

    介绍 Semaphore是什么 Semaphore可以称为信号量,这个原本是操作系统中的概念,是一种线程同步方法,配合PV操作实现线程之间的同步功能.信号量可以表示操作系统中某种资源的个数,因此可以用 ...

  3. go中semaphore(信号量)源码解读

    运行时信号量机制 semaphore 前言 作用是什么 几个主要的方法 如何实现 sudog 缓存 acquireSudog releaseSudog semaphore poll_runtime_S ...

  4. Java并发包中Semaphore的工作原理、源码分析及使用示例

    1. 信号量Semaphore的介绍 我们以一个停车场运作为例来说明信号量的作用.假设停车场只有三个车位,一开始三个车位都是空的.这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦.以后 ...

  5. 源码分析:Semaphore之信号量

    简介 Semaphore 又名计数信号量,从概念上来讲,信号量初始并维护一定数量的许可证,使用之前先要先获得一个许可,用完之后再释放一个许可.信号量通常用于限制线程的数量来控制访问某些资源,从而达到单 ...

  6. 【JUC】JDK1.8源码分析之Semaphore(六)

    一.前言 分析了CountDownLatch源码后,下面接着分析Semaphore的源码.Semaphore称为计数信号量,它允许n个任务同时访问某个资源,可以将信号量看做是在向外分发使用资源的许可证 ...

  7. Semaphore 源码分析

    Semaphore 源码分析 1. 在阅读源码时做了大量的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限,并且代码阅读起来没有 IDE 方便,所以在 github 上提供JDK1.8 的 ...

  8. 并发编程之 Semaphore 源码分析

    前言 并发 JUC 包提供了很多工具类,比如之前说的 CountDownLatch,CyclicBarrier ,今天说说这个 Semaphore--信号量,关于他的使用请查看往期文章并发编程之 线程 ...

  9. Java - "JUC" Semaphore源码分析

    Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例 Semaphore简介 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了 ...

  10. 【JDK】JDK源码分析-Semaphore

    概述 Semaphore 是并发包中的一个工具类,可理解为信号量.通常可以作为限流器使用,即限制访问某个资源的线程个数,比如用于限制连接池的连接数. 打个通俗的比方,可以把 Semaphore 理解为 ...

随机推荐

  1. Fiddler-- 安装HTTPs证书

    1. 现在很多带有比较重要信息的接口都使用了安全性更高的HTTPS,而Fiddler默认是抓取HTTP类型的接口,要想查看HTTPS类型接口就需要安装fiddler证书.   2.打开Fiddler, ...

  2. CentOS7修改默认运行级别

    新装了一个虚拟机,图形界面启动太慢,想调整一下按照以前的经验改运行级别,输入: vi /etc/inittab 然后发现跟之前不一样了,在inittab设置不再生效: # inittab is no ...

  3. device tree property ---- interrupt-names

    device tree source 的 interrupt-names property 會對應到 pltform_get_irq_byname() 的第二個參數. .dtsi or .dts in ...

  4. mybaits-spring demo 记

    代码:https://github.com/bobby96333/demo_spring_batis /pom.xml <?xml version="1.0" encodin ...

  5. vue做购物车

    写一点废话,昨天敲代码找bug,找了好久都没找到,后来一哥们找到他说,找代码的bug就像男女朋友吵架,女问男你错了没,男说错啦,女再问错哪了,男傻眼了不知道错哪.在找代码的过程中一直知道我错啦就是找不 ...

  6. linux sort排序命令

    1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. 2 sort的-u选项 在输出行中去除重复行. $ ...

  7. MySQL的读写分离---主从复制、主主复制

    1.复制是基于BinLog日志 存在三种日志格式:Statement:存储Sql语句,存储日志量是最小的.有可能复制不一致Row:存储event数据,存储日志量大,但是不能很直接进行读取:Mixed: ...

  8. 字符串aaaa......bbbb....ccc...dddddd用正则替换为abcd

    public static void main(String[] args) { String s = "aaaa......bbbb....ccc...dddddd"; Stri ...

  9. JavaScript自定义事件,动态添加属性

    根据事件的不同,可用的自定义方法也不同. document.createEvent('Event'); 实现主要有4个步骤: 1.创建事件. 2.初始化事件(三个参数:事件名,是否起泡,是否取消默认触 ...

  10. linux命令(5):netstat命令

    网络监控:netstat –in [显示所有配置接口的状态] 查看端口状态:netstat -anlp | grep 8080 [显示8080端口列出的监听状态] 查看某个进程软件名:netstat ...