在下面的教程中,我们将借助 Python 中的 Semaphore 了解多线程同步。
让我们从理解 Python 信号量开始。
理解信号量
- 信号量是一种同步结构。
- 信号量为线程提供了对有限资源的同步访问。
- 信号量可以被视为反映当前现有资源数量的变量。例如,在一个购物中心的停车场中,有几个特定级别的空位可以用作信号量。
- 信号量值不能小于零,也不能大于现有资源的总数。
- 信号量与两个操作相关联- 获取和释放。
- 当其中一个资源使用信号量进行同步时,该信号量的值会递减。
- 当其中一个资源使用信号量进行同步时,线程释放信号量,信号量的值递增。
- 信号量的概念是由荷兰计算机科学家埃德格·迪克斯特拉创造的。
- 信号量的两个操作,即获取和释放,分别由 Dijkstra 表示为 p 和 v ,其中 p 和 v 是荷兰语单词 proberen 和vehiogen的首字母。
- 单词 proberen 代表测试,而vehiogen代表荷兰语中的增量。
现在让我们理解 Python 编程语言中的信号量。
理解 Python 信号量
- 一类线程模块用于实现 Python 中信号量的概念。这个类被称为信号量
- Semaphore 类由一个构造器和两个函数组成,分别是 acquire() 和 release() 。
- acquire() 功能用于在计数大于零时减少信号量的计数。否则它会阻塞,直到计数大于零。
- release() 函数用于增加信号量的计数和唤醒等待信号量的一个线程。
让我们考虑下面的语法来创建一个信号量对象。
语法:
object_name = Semaphore(count)
说明:
在上面的语法中,对象名是信号量类的对象。信号量类的“计数”参数是允许同时访问的线程数。此参数的默认值为 1。
每当线程执行 acquire() 功能时,“计数参数的值将递减 1。每当线程执行释放()功能时,计数参数的值将增加 1。这种说法意味着,每当我们调用 acquire() 方法时, count 参数值会递减,而调用 release() 方法时, count 参数值会递增。
创建信号量对象的方法
情况 1: 在下面的情况中,我们在创建对象时没有在 Semaphore 类中指定参数。因此,计数变量的值为 1,因此只允许线程访问。本案正是锁定概念的翻版。
其语法如下所示:
语法:
object_name.Semaphore()
情况 2: 在下面的情况中,信号量类的一个对象可以由“ 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
说明:
在上面的代码片段中,我们已经导入了所需的模块,并为计数值为 4 的 Semaphore 类创建了一个对象。然后,我们在对象上使用 acquire() 函数定义了一个函数。然后,我们使用 for-loop 将该值迭代到 6。然后我们调用了 release() 函数并创建了多个线程。最后,我们已经使用 start() 函数调用了线程。