python多线程的信号量

2020年5月23日 / 39次阅读 / Last Modified 2020年5月23日
多线程

python threading模块还提供古老的信号量(semaphore)功能。

This is one of the oldest synchronization primitives in the history of computer science, invented by the early Dutch computer scientist Edsger W. Dijkstra (he used the names P() and V() instead of acquire() and release()). A semaphore manages an internal counter which is decremented by each acquire() call and incremented by each release() call. The counter can never go below zero; when acquire() finds that it is zero, it blocks, waiting until some other thread calls release().

信号量通过其内部的一个int变量来控制行为,P和V操作时原子的。默认情况下,threading.Semaphore创建的信号量,内部int的初始值为1,此时行为模式与一个lock互斥量没啥区别。不过,有一个细节,信号量的release(即V操作)会增加其内部的int值,而且可以多次release。

>>> import threading
>>> sp = threading.Semaphore()
>>> sp.acquire()
True
>>> sp.release()
>>> sp.release()

信号量多次release只会增加其内部int的值,而互斥量多次release,会有异常抛出。

为应对可以多次release信号量的问题,threading模块还提供了一个BoundedSemaphore类型,其可以控制信号量内部int的上限值。单纯的Semaphore类型,只能控制内部int不能小于0。

python官方对信号量的介绍:https://docs.python.org/3/library/threading.html#semaphore-objects

信号量的应用场景:

  1. 用于控制访问具有多个实例的某种资源。信号量的初值为可用资源数量。
  2. 有人写教材说可以用信号量控制多个线程的执行顺序,比如一定要控制A线程的某段代码执行成功后,才能执行B线程的某段代码。实现这个需求,原理是初始化一个内部int=0的信号量,A线程那段代码执行完后release,B线程那段代码之前acquire。

场景2的逻辑代码如下:

sp = threading.Semaphore(0)
...
# thread A
...  # code needs to run ahead
sp.release()
...
# thread B
...
sp.acquire()
...  # code needs to run after

不过,使用互斥量也可以实现场景2。创建一个mutex,然后先acquire,这个想过就相当于创建一个内部int=0的信号量。后面的逻辑就一样了。

-- EOF --

本文链接:https://www.pynote.net/archives/1975

留言区

《python多线程的信号量》有1条留言

电子邮件地址不会被公开。 必填项已用*标注

  • 麦新杰

    信号量的这个特性,决定了它在某种程度上可以申请和释放不在一个线程里。这句话我在一本很牛的书上看到的,我还不是很确定这是不是一个好的设计。 [回复]


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top