threading 之 semaphore信号量
admin
2023-07-12 10:45:26
0次

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异常

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...