您的位置:

Python 信号量

在下面的教程中,我们将借助 Python 中的 Semaphore 了解多线程同步。

让我们从理解 Python 信号量开始。

理解信号量

  1. 信号量是一种同步结构。
  2. 信号量为线程提供了对有限资源的同步访问。
  3. 信号量可以被视为反映当前现有资源数量的变量。例如,在一个购物中心的停车场中,有几个特定级别的空位可以用作信号量。
  4. 信号量值不能小于零,也不能大于现有资源的总数。
  5. 信号量与两个操作相关联- 获取和释放。
  6. 当其中一个资源使用信号量进行同步时,该信号量的值会递减。
  7. 当其中一个资源使用信号量进行同步时,线程释放信号量,信号量的值递增。
  8. 信号量的概念是由荷兰计算机科学家埃德格·迪克斯特拉创造的。
  9. 信号量的两个操作,即获取和释放,分别由 Dijkstra 表示为 p 和 v ,其中 p 和 v 是荷兰语单词 proberen 和vehiogen的首字母。
  10. 单词 proberen 代表测试,而vehiogen代表荷兰语中的增量。

现在让我们理解 Python 编程语言中的信号量。

理解 Python 信号量

  1. 一类线程模块用于实现 Python 中信号量的概念。这个类被称为信号量
  2. Semaphore 类由一个构造器和两个函数组成,分别是 acquire() 和 release() 。
  3. acquire() 功能用于在计数大于零时减少信号量的计数。否则它会阻塞,直到计数大于零。
  4. 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() 函数调用了线程。