threading 之 semaphore信号量

semaphore信号量的简单代码演示

import threading
import logging
import time

FORMAT = ‘%(threadName)s %(thread)d %(message)s‘
logging.basicConfig(format=FORMAT, level=logging.INFO)

def worker(s:threading.Semaphore):
    logging.info(‘in sub thread‘)
    logging.info(s.acquire())   # 获取信号量,计数器 -1
    logging.info(‘sub thread over‘)

s = threading.Semaphore(3)   # 创建3个信号量计数器
logging.info(s.acquire())
print(s._value)    # 看看现在信号量的内的数值是多少
logging.info(s.acquire())
print(s._value)
logging.info(s.acquire())
print(s._value)

threading.Thread(target=worker, args=(s, )).start()

time.sleep(2)

logging.info(s.acquire(False))    # 不阻塞,若获取不到信号量,则为False
logging.info(s.acquire(timeout=10))   # 设置超时时间,等待超时时间过了还未获取到信号,返回值为False

# 释放
logging.info(‘released‘)
s.release()   # 释放信号量,计数器i + 1

简单的资源池演示

import threading
import logging
import random

FORMAT = ‘%(threadName)s %(thread)d %(message)s‘
logging.basicConfig(format=FORMAT, level=logging.INFO)

class Conn:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name

class Pool:
    def __init__(self, count:int):
        self.count = count
        self.pool = [ self._connect(‘conn-{}‘.format(x)) for x in range(self.count)]

    def _connect(self, conn_name):
        return Conn(conn_name)

    def get_conn(self):
        conn = self.pool.pop()
        return conn

    def return_conn(self, conn:Conn):
        self.pool.append(conn)

pool = Pool(3)

def worker(pool:Pool):
    conn = pool.get_conn()
    logging.info(conn)
    threading.Event().wait(random.randint(1,4))
    pool.return_conn(conn)

for i in range(6):
    threading.Thread(target=worker, name=‘worker-{}‘.format(i), args=(pool,)).start()

使用semaphore来完善代码

import threading
import logging
import random

FORMAT = ‘%(threadName)s %(thread)d %(message)s‘
logging.basicConfig(format=FORMAT, level=logging.INFO)

class Conn:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name

class Pool:
    def __init__(self, count:int):
        self.count = count
        self.pool = [ self._connect(‘conn-{}‘.format(x)) for x in range(self.count)]
        self.semahore = threading.Semaphore(count)

    def _connect(self, conn_name):
        return Conn(conn_name)

    def get_conn(self):
        self.semahore.acquire()
        conn = self.pool.pop()
        return conn

    def return_conn(self, conn:Conn):
        self.pool.append(conn)
        self.semahore.release()

pool = Pool(3)

def worker(pool:Pool):
    conn = pool.get_conn()
    logging.info(conn)
    threading.Event().wait(random.randint(1,4))
    pool.return_conn(conn)

for i in range(6):
    threading.Thread(target=worker, name=‘worker-{}‘.format(i), args=(pool,)).start()

关于信号量release超出初始值范围的问题

当我们使用semaphore的时候,如果还未acquire,就release了,会产生什么问题?
会产生是的信号量的值+1,超出了原本设置semaphore的初始值,下面的例子说明了这个问题

import threading
import logging

FORMAT = ‘%(threadName)s %(thread)d %(message)s‘
logging.basicConfig(format=FORMAT, level=logging.INFO)

sema = threading.Semaphore(3)
logging.warning(sema.__dict__)
for _ in range(3):
    sema.acquire()

logging.warning(‘-----‘)
logging.warning(sema.__dict__)

for _ in range(4):
    sema.release()
logging.warning(sema.__dict__)

for _ in range(3):
    sema.acquire()
logging.warning(‘--------‘)
logging.warning(sema.__dict__)
sema.acquire()
logging.warning(‘======‘)
logging.warning(sema.__dict__)

所以这个这样的问题,可以使用BoundedSemaphore类来实现有界的信号量,若relase超出了初始值的范围,会抛出ValueError异常

原文地址:https://blog.51cto.com/windchasereric/2353569

时间: 2024-11-14 01:06:11

threading 之 semaphore信号量的相关文章

Semaphore(信号量)

Semaphore(信号量) 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去. 互斥锁只有1把锁,信号量有多把锁. import threading, time def run(n): semaphore.acquire()#信号量获取 time.sleep(1) print("run the thread: %s\n" % n) semaphore.rele

windows系统调用 semaphore信号量

1 #include "iostream" 2 #include "windows.h" 3 #include "cstring" 4 using namespace std; 5 6 HANDLE g_hSemThreads=INVALID_HANDLE_VALUE; 7 8 static DWORD WINAPI ThreadProc(LPVOID lpParam){ 9 LONG nPauseMs=reinterpret_cast<L

Semaphore信号量

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /**  * 信号量  *  * @author Vincent Zhao  * @version 1.0.0  * @Time 2015/4/20 15:57  */ public class SemaphoreDemo {     public st

CountDownLatch 闭锁、Semaphore信号量、Barrier栅栏

同步工具类可以是任何一个对象.阻塞队列可以作为同步工具类,其他类型的同步工具类还包括信号量(Semaphore).栅栏(Barrier).以及闭锁(Latch). 所有的同步工具类都包含一些特定的结构化属性:它们封装了一些状态,这些状态将决定执行同步工具类的线程是继续执行还是等待,此外还提供了一些方法对状态进行操作,以及另一些方法用于高效地等待同步工具类进入到预期状态. 1.闭锁 闭锁是一种同步工具类,可以延迟线程进度直到其到达终止状态.闭锁的作用相当于一扇门:在闭锁到达结束状态之前,这扇门一直

11.python并发入门(part6 Semaphore信号量)

一.什么是信号量. 信号量也是一种锁. 信号量的主要用途是用来控制线程的并发量的,BoundedSemaphore或Semaphore管理一个内置的计数器,每调用一次acquire()方法时,计数器-1,每调用一次release()方法时,内部计数器+1. 不过需要注意的是,Semaphore内部的计数器不能小于0!当它内部的计数器等于0的时候,这个线程会被锁定,进入阻塞状态,直到其他线程去调用release方法. BoundedSemaphore与Semaphore的唯一区别在于前者将在调用r

Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3534050.html Semaphore简介 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可

[笔记][Java7并发编程实战手册]3.2 资源的并发访问控制Semaphore信号量

[笔记][Java7并发编程实战手册]系列目录 简介 本文学习信号量Semaphore机制. Semaphore 本质是一个共享锁 内部维护一个可用的信号集,获取信号量之前需要先申请获取信号数量:用完之后,则需要释放信号量:如果不释放,那么其他等待线程则一直阻塞直到获取信号量或则被中断为止 本人的理解是:互斥锁是同一时间只能一个线程访问,而在这里,是同一时间允许获取到了信号量的线程并发访问,而没有获取到信号量的则必须等待信号量的释放: 将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,

【Linux】Semaphore信号量线程同步的例子

0. 信号量 Linux下的信号量和windows下的信号量稍有不同. Windows Windows下的信号量有一个最大值和一个初始值,初始值和最大值可以不同.  而且Windows下的信号量是一个[内核对象],在整个OS都可以访问到. Linux Linux下的信号量在创建的时候可以指定一个初始值,这个初始值也是最大值. 而且Linux下的信号量可以根据需要设置为是否是[进程间共享]的,如果不是进程间共享的则就是一个本进程局部信号量.  1.相关API int semt_init( semt

不用线程池,使用Semaphore信号量同样也可以控制Thread多线程的并行数量。

static Semaphore sem = new Semaphore(100, 100); for (int i = 0; i <1000; i++) { Thread td = new Thread(new ParameterizedThreadStart(方法)); td.Start(i); } static void 方法(object i) { sem.WaitOne();//自减信号量 方法体... 执行完成.... sem.Release();//信号量自增 }