一、简介
         信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用,负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待;而 release() 释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。

二、概念

Semaphore分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。

以一个停车场运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。

         在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。

在java中,还可以设置该信号量是否采用公平模式,如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部。 JDK中定义如下:

Semaphore(int permits, boolean fair)   

创建具有给定的许可数和给定的公平设置的Semaphore。

Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,在进程控制方面都有应用。Java并发库Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。

Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。

三、代码示例

public class TestSemaphore {

public static void main(String[] args) {

// 线程池

ExecutorService exec = Executors.newCachedThreadPool();

// 只能5个线程同时访问

final Semaphore semp = new Semaphore(5);

// 模拟20个客户端访问

for (int index = 0; index < 20; index++) {

final int NO = index;

Runnable run = new Runnable() {

public void run() {

try {

// 获取许可

semp.acquire();

System.out.println("Accessing: " + NO);

Thread.sleep((long) (Math.random() * 10000));

// 访问完后,释放

semp.release();

System.out.println("-----------------"+semp.availablePermits());

} catch (InterruptedException e) {

e.printStackTrace();

}

}

};

exec.execute(run);

}

// 退出线程池

exec.shutdown();

}

}

执行结果如下:

Accessing: 0

Accessing: 1

Accessing: 3

Accessing: 4

Accessing: 2

-----------------0

Accessing: 6

-----------------1

Accessing: 7

-----------------1

Accessing: 8

-----------------1

Accessing: 10

-----------------1

Accessing: 9

-----------------1

Accessing: 5

-----------------1

Accessing: 12

-----------------1

Accessing: 11

-----------------1

Accessing: 13

-----------------1

Accessing: 14

-----------------1

Accessing: 15

-----------------1

Accessing: 16

-----------------1

Accessing: 17

-----------------1

Accessing: 18

-----------------1

Accessing: 19

信号量 Semaphore的更多相关文章

  1. C# 多线程之一:信号量Semaphore

    通过使用一个计数器对共享资源进行访问控制,Semaphore构造器需要提供初始化的计数器(信号量)大小以及最大的计数器大小 访问共享资源时,程序首先申请一个向Semaphore申请一个许可证,Sema ...

  2. 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  3. 互斥锁Mutex与信号量Semaphore的区别

    转自互斥锁Mutex与信号量Semaphore的区别 多线程编程中,常常会遇到这两个概念:Mutex和Semaphore,两者之间区别如下: 有人做过如下类比: Mutex是一把钥匙,一个人拿了就可进 ...

  4. windows核心编程-信号量(semaphore)

    线程同步的方式主要有:临界区.互斥区.事件.信号量四种方式. 前边讲过了互斥器线程同步-----windows核心编程-互斥器(Mutexes),这章我来介绍一下信号量(semaphore)线程同步. ...

  5. 秒杀多线程第八篇 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <且不超过最大资源数量. 第三个參数能够用来传出先前的资源计数,设为NULL表示不须要传出. 注意:当 ...

  6. 转:【Java并发编程】之二十三:并发新特性—信号量Semaphore(含代码)

    载请注明出处:http://blog.csdn.net/ns_code/article/details/17524153 在操作系统中,信号量是个很重要的概念,它在控制进程间的协作方面有着非常重要的作 ...

  7. 多线程面试题系列(8):经典线程同步 信号量Semaphore

    前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数 ...

  8. java笔记--对信号量Semaphore的理解与运用

    java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或 ...

  9. 对信号量Semaphore的理解与运用

    转: java笔记--对信号量Semaphore的理解与运用 java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量, ...

随机推荐

  1. MapReduce自定义二次排序流程

    每一条记录开始是进入到map函数进行处理,处理完了之后立马就入自定义分区函数中对其进行分区,当所有输入数据经过map函数和分区函数处理完之后,就调用自定义二次排序函数对其进行排序. MapReduce ...

  2. 面向对象基础(class0425)字符串与集合

    常用类库 学习.net就是学习它的无数个类库怎么用,先看两个简单的 String 字符串,不可变特性.字符串可以看成字符数组 属性 Length 方法 IsNullOrEmpty() 静态方法 ToC ...

  3. matlab 函数说明--waitforbuttonpress

    这个函数的名称取得不是太好,一眼看去,好像是等待按键的意思,但是实际上它等待的是按键或者鼠标事件,他的功能描述如下: 停止脚本的执行,直至当前活动的窗口上检测到了鼠标按下事件或者有效的键盘事件(有效是 ...

  4. 【Linux 命令】Linux系统下强制用户下线——who,pkill

    [日期]2014年11月18日 [平台]Centos 6.5 [工具]who pkill [步骤] 1)准备工作 以root身份登录. 2)执行who命令,查看有哪些用户已登录到当前主机

  5. 初页CTO丁乐:分布式以后还能敏捷吗? - 极客头条 - CSDN.NET

    初页CTO丁乐:分布式以后还能敏捷吗? - 极客头条 - CSDN.NET

  6. [iOS基础控件 - 6.4] 汽车品牌展示 Model嵌套/KVC/TableView索引

    A.需求 1.使用汽车品牌名称头字母为一个Model,汽车品牌为一个Model,头字母Model嵌套品牌Model 2.使用KVC进行Model封装赋值 3.展示头字母标题 4.展示索引(使用KVC代 ...

  7. .Net中的Placeholder控件

    NET中的placeholder控件用来做什么的?其实PLACEHOLDER控件,是用来做动态加载用户自定义控件时,一个占位置作用的控件,比如 在从一个Web页面转换到另一个Web页面时,你的ASP. ...

  8. ACM_基础知识

    1. PI值的定义 const double PI = acos(-1.0); 2. system("pause")就是调用从程序中调用系统命令,而"pause" ...

  9. Winform- IrisSkin.dll轻松实现窗体换肤功能

    IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现winForm窗体换肤 然而IrisSkin2.dll只能在.NET Faremwork 4.0以及之前的版本使用,所以要在V ...

  10. Xcode8 创建NSManageObject subclass方法

    更新iOS8之后发现coredata也做了一些改变,创建本地的时候一脸懵逼,最后发现: 喜极而泣不能自已,(-.-!)