并发编程之同步机制(一):Semphore信号量
2017-10-09 14:12
267 查看
本文的目的是要分析信号量内部的实现流程,不深入信号量底层的实现细节AQS(将会有另外一篇文章分析),让读者能够理解信号量内部结构和调用流程。
Semaphore:内部持有一系列的许可(permit),acquire操作会被阻塞直到有足够多的许可可用,最后会占用这些许可;release操作会归还许可让阻塞的acquire操作获取。Semaphore作用是限制多线程同时正确某一资源(资源可以是某个对象,可以是某种行为,例如创建某一对象的权利,销毁某一对象的权利)。
从上面的定义,可以看到主要有几个概念:许可,获取,和释放。Semaphore信号量的作用显然就是维护许可,提供许可获取和释放功能。首先,我们可以想到许可是否可用,显然许可是具有一定状态的,例如0:代表不可用,1:代表可用等,那么Semaphore信号量是如何标识许可的状态特征的呢?
获取:肯定有个获取者(accquirer),获取者自身有以下特点:1)优先级不一样,有些高,有些低,就好比富人和穷人;2)获取者素质不太一样,有些获取者霸占许可一直不归还,有些获取者及时归还;3) 获取者有可能需要同时获取多个许可的需求;获取者在获取许可过程中显然也会有一些特点:1)获取者可能大量同时获取相同的许可,导致竞争非常激烈;2)获取者如果没有获取许可时一直等待,有些希望有许可时在通知他们;3)获取者获取并持有许可用,获取者死亡,那么许可怎么归还给Semaphore。
释放:获取者在释放过程中,相对来说就比较简单,只需要通知Semaphore,告诉不需要许可了即可。
因此,下面将从Semaphore,获取者和许可三者关系出发,分析三者之间的关系。
当我们创建Semaphore时,需要制定许可个数以及是否采用公平同步器,在Semaphore中,公正Semaphore是指当Semaphore中有获取许可操作时不允许当前获取许可操作成功,直接返回失败;不公平Semaphore则获取操作基于CAS机制不断操作处理,不分先后,这会导致后面的获取操作有可能先于前面操作获得许可,呈现不公平。
先看Semaphore结构,整体包括获取许可调用函数,超时获取许可调用函数,维护许可信息函数,和释放等操作。
首先分析acquire方法,该方法支持线程中断,一旦发生线程中断,直接跳出获取操作,向上抛出InterrputedException异常。
publicvoid
acquire()
throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
进入sync.acquireSharedInterruptibly(integer)方法。首先及时校验Thread是否处于已中断状态,之后尝试获取许可,如果获取失败,进入阻塞获取流程(在这个循环中会不断检测线程是否发生中断)。
publicfinal void
acquireSharedInterruptibly(int
arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
进入tryAcquire方法,该方法主要是获取信号量,不成功返回false,成功返回true,不阻塞,有明确结果返回。
publicboolean
tryAcquire() {
return sync.nonfairTryAcquireShared(1) >=
0;
}
进入tryAcquire(int,long,TimeUint)方法,首先判断是否发生线程中断,如未发生中断则进入tryAcquireSharedNanos方法(该方法会首先获取一次许可,未获取许可则进入指定时间段内轮询)。
publicboolean
tryAcquire(int
permits, long
timeout,
TimeUnit unit)
throws InterruptedException {
if (permits <
0) throw new
IllegalArgumentException();
return sync.tryAcquireSharedNanos(permits,
unit.toNanos(timeout));
}
Semaphore:内部持有一系列的许可(permit),acquire操作会被阻塞直到有足够多的许可可用,最后会占用这些许可;release操作会归还许可让阻塞的acquire操作获取。Semaphore作用是限制多线程同时正确某一资源(资源可以是某个对象,可以是某种行为,例如创建某一对象的权利,销毁某一对象的权利)。
从上面的定义,可以看到主要有几个概念:许可,获取,和释放。Semaphore信号量的作用显然就是维护许可,提供许可获取和释放功能。首先,我们可以想到许可是否可用,显然许可是具有一定状态的,例如0:代表不可用,1:代表可用等,那么Semaphore信号量是如何标识许可的状态特征的呢?
获取:肯定有个获取者(accquirer),获取者自身有以下特点:1)优先级不一样,有些高,有些低,就好比富人和穷人;2)获取者素质不太一样,有些获取者霸占许可一直不归还,有些获取者及时归还;3) 获取者有可能需要同时获取多个许可的需求;获取者在获取许可过程中显然也会有一些特点:1)获取者可能大量同时获取相同的许可,导致竞争非常激烈;2)获取者如果没有获取许可时一直等待,有些希望有许可时在通知他们;3)获取者获取并持有许可用,获取者死亡,那么许可怎么归还给Semaphore。
释放:获取者在释放过程中,相对来说就比较简单,只需要通知Semaphore,告诉不需要许可了即可。
因此,下面将从Semaphore,获取者和许可三者关系出发,分析三者之间的关系。
当我们创建Semaphore时,需要制定许可个数以及是否采用公平同步器,在Semaphore中,公正Semaphore是指当Semaphore中有获取许可操作时不允许当前获取许可操作成功,直接返回失败;不公平Semaphore则获取操作基于CAS机制不断操作处理,不分先后,这会导致后面的获取操作有可能先于前面操作获得许可,呈现不公平。
先看Semaphore结构,整体包括获取许可调用函数,超时获取许可调用函数,维护许可信息函数,和释放等操作。
首先分析acquire方法,该方法支持线程中断,一旦发生线程中断,直接跳出获取操作,向上抛出InterrputedException异常。
publicvoid
acquire()
throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
进入sync.acquireSharedInterruptibly(integer)方法。首先及时校验Thread是否处于已中断状态,之后尝试获取许可,如果获取失败,进入阻塞获取流程(在这个循环中会不断检测线程是否发生中断)。
publicfinal void
acquireSharedInterruptibly(int
arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
进入tryAcquire方法,该方法主要是获取信号量,不成功返回false,成功返回true,不阻塞,有明确结果返回。
publicboolean
tryAcquire() {
return sync.nonfairTryAcquireShared(1) >=
0;
}
进入tryAcquire(int,long,TimeUint)方法,首先判断是否发生线程中断,如未发生中断则进入tryAcquireSharedNanos方法(该方法会首先获取一次许可,未获取许可则进入指定时间段内轮询)。
publicboolean
tryAcquire(int
permits, long
timeout,
TimeUnit unit)
throws InterruptedException {
if (permits <
0) throw new
IllegalArgumentException();
return sync.tryAcquireSharedNanos(permits,
unit.toNanos(timeout));
}
相关文章推荐
- Java并发编程的艺术(八)——闭锁、同步屏障、信号量详解
- 秋招准备-Java-并发编程-同步机制与synchronized(二)
- Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)
- 并发编程11.原子变量与非阻塞同步机制
- 并发编程 21—— 原子变量和非阻塞同步机制
- JAVA 并发编程实践 - 原子变量与非阻塞同步机制 笔记
- 多线程并发编程之原子变量与非阻塞同步机制
- 并发编程实战学习笔记(十一)-原子变量与非阻塞同步机制
- java并发编程笔记3-同步容器&并发容器&闭锁&栅栏&信号量
- Linux多线程编程入门-同步机制-信号量
- Java并发:线程间同步机制:条件队列和同步工具类
- 【Java并发编程实战】—– AQS(四):CLH同步队列
- 并发编程之同步锁
- linux操作系统编程——共享内存的读写(采用信号机制进行同步互斥)
- java多线程:并发包中的信号量和计数栓的编程模型
- java 多线程并发 synchronized 同步机制及方式
- Java并发编程--5.信号量和障碍器
- python并发编程之多线程2------------死锁与递归锁,信号量等
- Linux 2.4 内核的同步机制(1) (信号量)
- 进程同步---生产者与消费者问题以及进程同步机制--信号量及P、V操作