Python 信号量
在接下来的教程中,我们将通过Python中的信号量来理解多线程同步。
让我们从理解Python信号量开始。
理解信号量
- 信号量是一种同步构造。
- 信号量为线程提供对一定数量资源的同步访问。
- 信号量可以被看作是反映当前存在的资源数量的变量。例如,购物中心停车场的某个楼层有几个可用的车位就是一个信号量。
- 信号量的值不能小于零,也不能大于现有资源的总数。
- 信号量与两个操作相关联 – 获取 和 释放 。
- 当其中一个资源通过信号量进行同步被线程” 获取 “时,信号量的值减少。
- 当其中一个资源通过信号量进行同步被线程” 释放 “时,信号量的值增加。
- 信号量的概念由荷兰计算机科学家 Edsger Dijkstra 创造。
- 信号量的两个操作,即 获取 和 释放 ,分别由Dijkstra以 p 和 v 表示,其中 p 和 v 是荷兰语单词 proberen 和 vehogen 的首字母。
- 单词 proberen 代表 测试 ,而 vehogen 代表 增加 。
现在让我们了解Python编程语言中的信号量。
理解Python信号量
- 在Python中,使用 threading 模块的一个类来实现信号量的概念。这个类被称为 Semaphore
- Semaphore类包括一个构造函数和两个函数, acquire() 和 release() 。
- acquire() 函数用于在计数大于零时减少信号量的计数。否则,它会阻塞直到计数大于零。
- release() 函数用于增加信号量的计数并唤醒等待在信号量上的一个线程。
让我们考虑以下语法以创建信号量对象。
语法:
object_name = Semaphore(count)
解释:
在上面的语法中, object_name 是 Semaphore 类的对象。Semaphore类的 ‘count’ 参数是允许同时访问的线程数。此参数的默认值为1。
每当线程执行 acquire() 函数时,”count”参数的值将减少1。每当线程执行 release() 函数时,”count”参数的值将增加1。这个语句意味着每当我们调用 acquire() 方法时,”count”参数的值将被减少,而调用 release() 方法时,”count”参数的值将被增加。
创建Semaphore对象的方法
情况1:
在下面的情况中,我们在创建对象时没有指定Semaphore类内的参数。因此,由于count变量的值为1,只有一个线程可以访问。这种情况与 Lock 概念完全相同。
相同的语法如下所示:
语法:
object_name.Semaphore()
情况2: 在下面的情况中,Semaphore类的对象可以被 n 个线程同时访问。其余的线程必须等待直到信号量释放。
相同操作的语法如下所示:
语法:
object_name.Semaphore(n)
让我们考虑以下示例,以正确理解完整概念。
示例:
# importing the modules
from threading import *
import time
# creating thread instance where count = 3
my_obj = Semaphore(4)
# creating instance
def show(the_name):
# calling acquire method
my_obj.acquire()
for n in range(6):
print('Javatpoint, ', end = '')
time.sleep(1)
print(the_name)
# calling release method
my_obj.release()
# creating multiple thread
thread_1 = Thread(target = show , args = ('Thread 1',))
thread_2 = Thread(target = show , args = ('Thread 2',))
thread_3 = Thread(target = show , args = ('Thread 3',))
thread_4 = Thread(target = show , args = ('Thread 4',))
thread_5 = Thread(target = show , args = ('Thread 5',))
thread_6 = Thread(target = show , args = ('Thread 6',))
# calling the threads
thread_1.start()
thread_2.start()
thread_3.start()
thread_4.start()
thread_5.start()
thread_6.start()
输出
Javatpoint, Javatpoint, Javatpoint, Javatpoint, Thread 1
Thread 3
Thread 4
Thread 2
Javatpoint, Javatpoint, Javatpoint, Javatpoint, Javatpoint, Javatpoint, Thread 1
Thread 5
Javatpoint, Javatpoint, Thread 6
Thread 3
Thread 4
Javatpoint, Javatpoint, Thread 2
Javatpoint, Javatpoint, Thread 5
Javatpoint, Thread 1
Javatpoint, Thread 3
Javatpoint, Thread 6
Thread 2
Thread 4
Javatpoint, Javatpoint, Javatpoint, Thread 5
Javatpoint, Thread 1
Javatpoint, Thread 3
Javatpoint, Thread 6
Thread 2
Javatpoint, Javatpoint, Thread 4
Javatpoint, Thread 5
Javatpoint, Thread 1
Thread 3
Javatpoint, Javatpoint, Thread 2
Thread 6
Javatpoint, Javatpoint, Thread 4
Javatpoint, Thread 5
Javatpoint, Thread 1
Thread 3
Thread 2
Thread 6
Javatpoint, Thread 4
Thread 5
Thread 6
解释:
在上述代码片段中,我们导入了所需的模块并创建了一个 Semaphore 类的对象,该对象具有计数值为4。然后,我们使用 acquire() 函数在对象上定义了一个函数。然后,我们使用 for循环 来迭代值到6。然后,我们调用了 release() 函数并创建了多个线程。最后,我们使用 start() 函数调用了这些线程。