多线程编程之信号量锁

468 阅读2分钟

1 基本介绍

semaphore信号量锁也是根据条件锁来做的,他与条件锁、事件锁的区别如下:

条件锁:一次可以放行任意个处于“等待”状态的线程

事件锁:一次可以放行全部的处于“等待”状态的线程

信号量锁:通过规定,成批的放行特定个处于“上锁”状态的线程

2 相关方法

方法描述
threading.Semaphore()返回一个信号量锁对象
lockObject.acquire(blocking=True, timeout=1)上锁,当一个线程在执行被上锁代码块时,将不允许切换到其他线程运行,默认锁失效时间为1秒
lockObject.release()解锁,当一个线程在执行未被上锁代码块时,将允许系统根据策略自行切换到其他线程中运行

3 使用示例

这里有2个示例

example01:

import threading
import time
​
​
def run(n, semaphore):
    semaphore.acquire()
    time.sleep(3)
    print('run the thread:%s\n' % n)
    semaphore.release()
​
​
def main():
    # 最多允许两个线程同时运行
    semaphore = threading.BoundedSemaphore(2)
    for num in range(4):
        t = threading.Thread(target=run, args=(f't-{num}', semaphore))
        t.start()
​
​
if __name__ == '__main__':
    main()

result:

run the thread:t-1
​
run the thread:t-0
​
run the thread:t-3
run the thread:t-2

example 02:

import threading
import time
​
sema = threading.BoundedSemaphore(2)
​
t_total = 0
​
​
def A(num):
    sema.acquire()
    print('Thread: %s' % num)
    time.sleep(1)
    sema.release()
    return
​
​
def run_cmp_single():
    for i in range(5):
        t_a = threading.Thread(target=A, args=(i + 1,))
        t_a.start()
​
​
if __name__ == '__main__':
    run_cmp_single()

result;

Thread: 1
Thread: 2
Thread: 3
Thread: 4
Thread: 5

4 with语句

与同步锁一样,threading.Semaphore()对象中也实现了 enter()exit()方法,因此我们也可以像同步锁一样,使用with语句进行上下文管理形式来进行信号量锁的加锁解锁操作。

示例代码如下:

import threading
import time
​
​
def run(n, semaphore):
    with semaphore:
        time.sleep(3)
        print('run the thread:%s\n' % n)
​
​
def main():
    # 最多允许两个线程同时运行
    semaphore = threading.BoundedSemaphore(2)
    for num in range(4):
        t = threading.Thread(target=run, args=(f't-{num}', semaphore))
        t.start()
​
​
if __name__ == '__main__':
    main()

result:

run the thread:t-1
​
run the thread:t-0
​
run the thread:t-3
run the thread:t-2

\