Semaphore-信号灯机制
我们创建一个可扩展大小的线程池,并且需要在线程池内同时让有限数目的线程并发运行时,就需要用到Semaphore(信号灯机制),Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目,它是一个计数信号量,从概念上讲,信号量维护了一个许可集合,如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可,每个release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
在线程池内创建线程并运行时,每个线程必须从信号量获取许可,从而保证可以使用该项。该线程结束后,线程返回到池中并将许可返回到该信号量,从而允许其他线程获取该项。注意,调用acquire() 时无法保持同步锁定,因为这会阻止线程返回到池中。信号量封装所需的同步,以限制对池的访问,这同维持该池本身一致性所需的同步是分开的。下面通过一个例子加以说明:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; //信号灯测试
public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Semaphore sp = new Semaphore(3);//开启3个信号灯
for (int i = 0; i < 10; i++) {
Runnable runnable = new Runnable() {
public void run() {
try {
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"进入,当前已有" + (3 - sp.availablePermits()) + "个并发");
try {
Thread.sleep((long) (Math.random() * 1000));//休息的时间越短的话,就越容易打乱进入
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"即将离开");
sp.release();
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
"已离开,当前已有" + (3 - sp.availablePermits()) + "个并发");
}
};
service.execute(runnable);
}
} }
该例子定义了一个newCachedThreadPool,在该Pool中利用for循环同时创建5个线程,现在通过Semaphore,创建一个只允许在线程池中有3个线程并发运行,sp.acquire()表示某个线程获得了一个信号灯,开始运行,在运行结束时,通过sp.release()还回这个信号灯,以便剩下的线程获得信号灯运行,sp.availablePermits()指的是当前信号灯库中有多少个可以被使用,由于例子中定义有3个信号灯,所以3-sp.availablePermits()就代表了当前有多少个线程在并发运行.
Semaphore作为互斥锁使用:
当信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。按此方式使用时,与传统互斥锁最大不同就是在释放的时候并不是必须要拥有锁的对象释放,也可以由其他的对象释放,因为信号量没有所有权的概念。在某些专门的上下文(如死锁恢复)中这会很有用。
Semaphore的构造方法有两种:
第一种:
Semaphore(int permits) //用给定的许可数和非公平的公平设置创建一个 Semaphore。
第一种构造方法创建的信号灯,现在在获取的时候是随机的,没有一定的顺序,例如上例中,在前三个线程中的一个运行完毕以后,释放一个信号灯,剩下的两个线程就会随机的一个线程得到这个信号灯而运行。
第二种:
Semaphore(int permits, boolean fair) //用给定的许可数和给定的公平设置创建一个 Semaphore
第二种构造方法可选地接受一个公平 参数。当设置为 false 时,此类不对线程获取许可的顺序做任何保证。特别地,闯入 是允许的,也就是说可以在已经等待的线程前为调用acquire() 的线程分配一个许可,从逻辑上说,就是新线程将自己置于等待线程队列的头部。当公平设置为 true 时,信号量保证对于任何调用acquire() 方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。注意,FIFO 排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了acquire(),但是却在该线程之后到达排序点,并且从方法返回时也类似。还要注意,非同步的tryAcquire() 方法不使用公平设置,而是使用任意可用的许可。
通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。
Semaphore-信号灯机制的更多相关文章
- java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用
先来讲解一下Semaphore信号灯的作用: 可以维护当前访问自身的线程个数,并提供了同步机制, 使用semaphore可以控制同时访问资源的线程个数 例如,实现一个文件允许的并发访问数. 请看下面 ...
- System IPC 与Posix IPC(semaphore信号灯)
POSIX下IPC主要包括三种: posix message queue posix semaphores posix shared memory sysytem v IPC包括: system v ...
- Java多线程——Semaphore信号灯
Semaphore可以维护当前访问自身的线程个数,并提供了同步机制.使用Semaphore可以控制同时访问资源的线程个数(即允许n个任务同时访问这个资源),例如,实现一个文件允许的并发访问数. Sem ...
- 锁机制(Lock) 信号量机制(Semaphore) 事件机制(Event)
IPC 进程间通信(inter-Process Communicate) 锁机制(Lock) l = Lock() 开启一个锁机制(实例化) 一把锁配一个钥匙 l.acquire() 获得钥匙 ...
- java Semaphore信号灯
Semaphore实现的功能就类似2个公用电话,假如有10个人要打电话:那么只能2个人占有电话,8个需要等待.当2个人中 的任何一个人让开后,其中等待的另外8个人中又有一个人可以使用了等待的8个人中可 ...
- ArrayBlockingQueue 阻塞队列和 Semaphore 信号灯的应用
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public cl ...
- JAVA-Semaphore信号灯-可实现维护自身线程访问数
import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Ex ...
- Linux多线程同步机制
http://blog.163.com/he_junwei/blog/static/19793764620141711130253/ http://blog.csdn.net/h_armony/art ...
- python lock, semaphore, event实现线程同步
lock 机制不管你是java, C#, 还是python都是常用的线程同步机制, 相比较C# 的锁机制, python的加锁显得比较简单, 直接调用threading 标准库的lock 就可以了. ...
随机推荐
- 全局描述符表(GDT)——《x86汇编语言:从实模式到保护模式》读书笔记09
在进入保护模式之前,我们先要学习一些基础知识.今天我们看一下全局描述符表(Global Descriptor Table, 简称GDT). 同实模式一样,在保护模式下,对内存的访问仍然使用段地址加偏移 ...
- mongodb-导出数据到csv文件或json文件
在mongodb的bin目录下, 有一个mongoexport, 可用于数据的导出 [wenbronk@localhost bin]$ ./mongoexport --help Usage: mong ...
- 配置私有仓库(使用registry镜像搭建一个私有仓库)
在使用Docker一段时间后,往往会发现手头积累了大量的自定义镜像文件,这些文件通过公有仓库进行管理并不方便:另外有时候只是希望在内部用户之间进行分享,不希望暴露出去.这种情况下,就有必要搭建一个本地 ...
- Java中float和double转换的问题
为什么double转float不会出现数据误差,而float转double却误差如此之大? double d = 3.14; float f = (float)d; System.out.prin ...
- JSON必知必会
知识点比较杂,简单的以列表形式罗列知识点 1.json是基于javascript对象字面量的,所以他们看起来很像.但是js对象字面量不需要给名称-值对中的名称两边加上双引号.而在JSON中,却是必要的 ...
- .Net Actor 服务端开发框架,Newbe.Claptrap 项目周报 1 - 还没轮影,先用轮跑
Newbe.Claptrap 项目周报 1,第一周代码写了一点.但主要还是考虑理论可行性. 第一次接触本框架的读者,可以先点击此处阅读本框架相关的基础理论和工作原理. 周报是啥? 成功的开源作品,离不 ...
- 数据库初识--从MySQL 出发
要学Web 开发,也得先对数据库有所了解呀.数据库分门别类,多种多样,目前我选择了 MySQL . 看了 MySQL,觉得数据库处理也不是很难,主要就是一些对数据的处理,MySQL 主要就是一些命令的 ...
- 解决 Jquery UI Tooltip 用在Select 的BUG
今天遇到一个奇葩问题, 在chrome下一切正常的 页面,在IE 下Select无法选中! 是的 ,就是无法选中!!! 效果就是这样的.http://jsfiddle.net/slolife/dp4 ...
- Microsoft .NET Pet Shop 4: Migrating an ASP.NET 1.1 Application to 2.0
249 out of 297 rated this helpful - Rate this topic Gregory Leake Microsoft Corporation Alan Le, Ale ...
- AVPlayer 音乐播放后台播放,以及锁屏主题设置
第一步:在appDelegate中通知app支持后台播放:在方法 - (BOOL)application:(UIApplication *)application didFinishLaunching ...