semaphore

多线程同步的三大神器

萝らか妹 提交于 2020-02-18 11:12:39
本文出自 代码大湿 代码大湿 实现多个线程同步一般有三种方式(CountDownLatch,CyclicBarrier,Semaphore) 1:CountDownLatch一般用于一个线程等待其他多个线程的同步。其countDown方法将计数器减1。await方法在计数器不为0的时候都是阻塞状态(await不改变计数器的值)。 2:CyclicBarrier的await将计数器值加1,其值不为构造器中的参数的时候是阻塞的。而且CyclicBarrier还可以重复利用。等到计数器为0的时候开始执行。 3: Semaphore(信号量)是实现多线程的资源共享。 看CountDownLatch的例子: package demo; import java.util.concurrent.CountDownLatch; public class Main { public static void main(String[] args) { CountDownLatch countDownLatch=new CountDownLatch(5); for(int i=0;i<5;i++){ new Thread(new r(countDownLatch)).start(); } try { countDownLatch.await(); System.out.println("主线程可以执行了

python多线程-Semaphore(信号对象)

孤者浪人 提交于 2020-02-18 10:56:55
Semaphore(value=1) Semaphore 对象内部管理一个计数器,该计数器由每个 acquire() 调用递减,并由每个 release() 调用递增。计数器永远不会低于零,当 acquire() 发现计数器为零时,线程阻塞,等待其他线程调用 release() 。 Semaphore 对象支持上下文管理协议。 方法: acquire(blocking=True, timeout=None) 获取信号。 当 blocking=True 时:如果调用时计数器大于零,则将其减1并立即返回。如果在调用时计数器为零,则阻塞并等待,直到其他线程调用 release() 使其大于零。这是通过适当的互锁来完成的,因此如果多个 acquire() 被阻塞, release() 将只唤醒其中一个,这个过程会随机选择一个,因此不应该依赖阻塞线程的被唤醒顺序。 返回值为 True 。 当 blocking=False 时,不会阻塞。如果调用 acquire() 时计数器为零,则会立即返回 False . 如果设置了 timeout 参数,它将阻塞最多 timeout 秒。如果在该时间段内没有获取锁,则返回 False ,否则返回 True 。 release() 释放信号,使计数器递增1。当计数器为零并有另一个线程等待计数器大于零时,唤醒该线程。 BoundedSemaphore

【Java并发工具类】Semaphore

风格不统一 提交于 2020-02-16 00:21:04
前言 1965年,荷兰计算机科学家Dijkstra提出的信号量机制成为一种高效的进程同步机制。这之后的15年,信号量一直都是并发编程领域的终结者。1980年,管程被提出,成为继信号量之后的在并发编程领域的第二个选择。目前几乎所有的语言都支持信号量机制,Java也不例外。Java中提供了 Semaphore 并发工具类来支持信号量机制。下面我们就来了解Java实现的信号量机制。 首先介绍信号量模型,然后介绍如何使用,最后使用信号量来实现一个限流器。 信号量模型 信号量模型图(图来自参考[1]): 信号量模型总结为:一个计数器、一个等待队列和三个对外调用的方法。 计数器和等待队列时对外透明的,所有我们只能通过三个对外方法来访问计数器和等待队列。 init() :设置计数器的初始值。 down() :计数器的值减一。如果此时计数器的值小于0,则当前线程插入等待队列并阻塞,否则当前线程可以继续执行。 up() :计数器的值加一。如果此时计数器的值小于或者等于0,则唤醒等待队列中的一个线程,并将其从等待队列中移除。 这三个方法都是原子性的,由实现信号量模型的方法保证。在Java SDK中,信号量模型是由 java.util.concurrent.Semaphore 实现。 信号量模型代码化大致类似如下: class Semaphore{ int count; // 计数器 Queue

IPC通信:Posix信号灯

假装没事ソ 提交于 2020-02-12 23:23:46
  信号灯用来实现 同步 ——用于多线程,多进程之间同步共享资源(临界资源)。信号灯分两种,一种是有名信号灯,一种是基于内存的信号灯。 有名信号灯 ,是根据外部名字标识,通常指代文件系统中的某个文件。 而基于内存的信号灯 ,它主要是把信号灯放入内存的,基于内存的信号灯,同步多线程时,可以放到该多线程所属进程空间里;如果是同步多进程,那就需要把信号灯放入到共享内存中(方便多个进程访问)。   有名信号灯和基于内存的信号灯,具体区别体现在创建和销毁两个函数。有名信号灯使用sem_open和sem_close函数。基于内存的信号灯使用sem_init和sem_destroy函数。sem_init的参数可以控制是同步多线程,还是多进程;且该函数只能调用1次,因为调用后信号灯就存在了( 内存指针存在)。一般,使用基于内存的信号灯同步同进程多线程,使用有名信号灯同步多进程。 有名信号灯同步多线程: 1 1.sem_open函数。 2 功能:创建并初始化信号灯,如果存在就返回存在的信号灯。 3 头文件:#include <semaphore.h> 4 函数原型:sem_t * sem_open(const char * name,int oflag,mode_t mode,unsigned int value); 5 或者:sem_t * sem_open(const char * name

Java多线程(二)

最后都变了- 提交于 2020-02-12 11:33:30
个人博客 http://www.milovetingting.cn Java多线程(二) 前言 本文为学习Java相关知识所作笔记,参考以下资料: https://github.com/Snailclimb/JavaGuide ,感谢原作者的分享! JAVA 锁 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。 java 中的乐观锁基本都是通过 CAS 操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。 悲观锁 悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会 block 直到拿到锁。java中的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock。 自旋锁 自旋锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态

Semaphore

假装没事ソ 提交于 2020-02-08 12:35:20
背景 Semaphore 用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。信号量还可以用来实现某种资源池,或者对容器施加边界。 Semaphore 管理着一组许可(permit),许可的初始数量可以通过构造函数设定,操作时要首先获得许可,才能进行操作,操作完成之后释放许可。如果没有获取许可,则阻塞直到有许可被释放。如果初始化一个许可为 1 的 Semaphore 那就相当于初始化了一个不可重入的互斥锁。 源码分析 构造函数 public Semaphore(int permits) { sync = new NonfairSync(permits); } public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits); } 两个构造方法都必须提供许可数量。第二个构造用法用于指定公平模式还是非公平模式。与 ReentrantLock 中的公平锁和非公平锁一样。公平信号量获取时,如果当前线程不在 CLH 队列的头部,则需要排队等候,对于非公平信号量而言,无论当前线程处于 CLH 队列的任何位置都可以直接获取。 获取许可 Semaphore 提供了四种获取许可的方法,分别如下: //获取一个许可证(响应中断)

Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

半城伤御伤魂 提交于 2020-02-08 00:16:41
在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法。 以下是本文目录大纲: 一.CountDownLatch用法 二.CyclicBarrier用法 三.Semaphore用法 若有不正之处请多多谅解,并欢迎批评指正。 一.CountDownLatch用法 CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。 CountDownLatch类只提供了一个构造器: public CountDownLatch(int count) { }; //参数count为计数值 然后下面这3个方法是CountDownLatch类中最重要的方法: public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 public boolean await(long timeout, TimeUnit unit) throws InterruptedException

Java 并发包中的高级同步工具

送分小仙女□ 提交于 2020-02-07 14:53:54
Java 并发包中的高级同步工具 Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线程池的创建类 ThreadPoolExecutor、Executors 等; 提供了各种锁,如 Lock、ReentrantLock 等; 提供了各种线程安全的数据结构,如 ConcurrentHashMap、LinkedBlockingQueue、DelayQueue 等; 提供了更加高级的线程同步结构,如 CountDownLatch、CyclicBarrier、Semaphore 等。 在前面的章节中我们已经详细地介绍了线程池的使用、线程安全的数据结构等,本文我们就重点学习一下 Java 并发包中更高级的线程同步类:CountDownLatch、CyclicBarrier、Semaphore 和 Phaser 等。 CountDownLatch 介绍和使用 CountDownLatch(闭锁)可以看作一个只能做减法的计数器,可以让一个或多个线程等待执行。 CountDownLatch 有两个重要的方法: countDown():使计数器减 1; await():当计数器不为 0 时,则调用该方法的线程阻塞,当计数器为 0 时,可以唤醒等待的一个或者全部线程。

JAVA并发包(二十五):Semaphore

≯℡__Kan透↙ 提交于 2020-02-06 01:02:55
Semaphore也是高并发中控制并发量的工具,它维护一系列的运行许可。每个线程运行之前来获取许可,许可的数量有限,只有获得的线程才能继续运行,否则阻塞等待。 通过前面对CountDownLatch的学习,现在来理解Semaphore应该会轻松点。 一、基本代码结构 public class Semaphore implements java . io . Serializable { /** Semaphore的核心逻辑在Sync */ private final Sync sync ; /** Sync继承于AQS */ abstract static class Sync extends AbstractQueuedSynchronizer { Sync ( int permits ) { setState ( permits ) ; } final int getPermits ( ) { return getState ( ) ; } } /** 构造器默认使用非公平模式 */ public Semaphore ( int permits ) { sync = new NonfairSync ( permits ) ; } /** 指定是否使用公平模式 */ public Semaphore ( int permits , boolean fair ) { sync =

Semaphore源码解析

非 Y 不嫁゛ 提交于 2020-02-01 11:08:32
Semaphore Semaphore 信号量,许可,用于控制在一段时间内,可并发访问执行的线程数量,基于AQS实现。 获取许可,支持公平和非公平模式,默认非公平模式。公平模式无论是否有许可,都会判断是否线程在排队,如果有线程排队,获取线程立即失败,进入排队;非公平模式无论许可是否充足,直接尝试获取许可。 可用于网关限流,或者资源限制(如最大可发起连接数)。 由于 release() 释放许可时,未对释放许可数做限制,所以可以通过该方法增加总的许可数量; reducePermits() 方法可以减少总的许可数量,通过这两个方法可以达到动态调整许可的目的。 内部类同步器 abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 1192457210091910933L; /** * 赋值state为总许可数 */ Sync(int permits) { setState(permits); } /** * 剩余许可数 */ final int getPermits() { return getState(); } /** * 自旋 + CAS非公平获取 */ final int nonfairTryAcquireShared