Python中的semaphores

在本指南中,我们将学习如何使用信号灯处理Python中的多线程。如何对线程和受限制的资源进行同步访问?

信号灯

一个同步控制器就是一个信号灯。Semaphore为线程提供对有限数量资源的同步访问。

一个semaphore可以被看作是一个变量,代表现在有多少资源可用。

例如,商场中作为信号灯的停车场,在某一层有几个空位。

semaphore的值必须大于或小于可用资源。acquirerelease 的操作与信号灯有关。

当用于同步的资源之一被一个线程 “获得 “时,semaphore的值会减少。当一个同步资源被线程 “释放 “时,semaphore的值会增加。

Python中的信号灯

Python对信号灯概念的实现使用了来自threading 模块的一个类。Semaphore 是这个类的名字。

一个acquire()release() 函数都包含在Semaphore 类中,同时还有一个函数构造器。

如果semaphore计数超过0,则使用acquire() 函数来降低计数。如果不是,它将阻塞,直到计数大于0。

坐在信号灯上的一个线程通过使用release() 函数被唤醒,这也会增加信号灯的计数。现在我们来了解一下信号灯的语法。

object_name = threading.Semaphore(count)

在上面的语法中,Semaphore 类对象是由object_name 表示的。

允许一次访问的线程数由Semaphore 类的count 参数指定。这个参数的默认值是1。

每当一个线程使用acquire() 函数时,count 参数的值就减少1。每当一个线程使用release() 函数时,count 参数的值就会增加1。

根据这一声明,无论何时我们调用acquire() 方法,count 参数的值都会减少;然而,当我们调用release() 函数时,count 参数的值将会增加。看一下下面的代码。

#import threading module
import threading
#creating instance of semaphore
sema = threading.Semaphore(1)
def test():
    #appling semaphore
    print(f"Value Of Semaphore --> {sema._value}")
    sema.acquire()
    print(f"acquired lock --> {threading.current_thread().name}")
    print(f"Value Of Semaphore --> {sema._value}")
    print(f"release lock --> {threading.current_thread().name}")
    sema.release()
    print(f"Value Of Semaphore --> {sema._value}")
#initializing threads
t1 = threading.Thread(target=test)
t2 = threading.Thread(target=test)
t3 = threading.Thread(target=test)
#executing threads
t1.start()
t2.start()
t3.start()

如果count 被设置为1,线程将被同步,如上面的代码。如果我们看一下上面代码的输出,我们会发现,将是第一和第二线程,然后第三线程将可以访问acquirerelease 之间的代码。

Value Of Semaphore --> 1
Value Of Semaphore --> 1
acquired lock --> Thread-1 (test)
Value Of Semaphore --> 0
Value Of Semaphore --> 0
release lock --> Thread-1 (test)
Value Of Semaphore --> 1
acquired lock --> Thread-2 (test)
Value Of Semaphore --> 0
release lock --> Thread-2 (test)
Value Of Semaphore --> 1
acquired lock --> Thread-3 (test)
Value Of Semaphore --> 0
release lock --> Thread-3 (test)
Value Of Semaphore --> 1

如果你将count 的值从1改为2,你将允许两个线程同时访问受限的代码。所以,输出结果将是不同的。

Value Of Semaphore --> 2
acquired lock --> Thread-1 (test)
Value Of Semaphore --> 1
Value Of Semaphore --> 1
release lock --> Thread-1 (test)
Value Of Semaphore --> 1
Value Of Semaphore --> 1
acquired lock --> Thread-3 (test)
acquired lock --> Thread-2 (test)
Value Of Semaphore --> 0
Value Of Semaphore --> 0
release lock --> Thread-2 (test)
release lock --> Thread-3 (test)
Value Of Semaphore --> 1
Value Of Semaphore --> 2

注意,信号灯释放线程的时间是基于你的设备的速度,每次都会有所不同。你可以通过改变semaphore实例中count 的值来测试上面的代码。