前言
信号量是由系统管理提供的抽象数据类型,用于多线程间资源同步,可以在多个线程中操作一个信号量。
1.使用
import threading
semphore = threading.Semaphore()
semphore.acquire()
semphore.release()
首先使用threading.Semaphore()创建信号量实例,参数指定可以根据实际情况传递,表示内部维护的计数器大小,默认为1。Ps:某个网站上有说是线程访问的数量,不过忘记了,当前以计数器大小为准,源码中也是说计数器。
如果要获取到临界资源,调用acquire(),计数-1,直到为0时阻塞。资源传递完后,调用release(),计数+1。
注意:调用完acquire之后无需调用release,否则相当于又去将计数器+1,如果线程一直运行的话,将陷入循环,消耗CPU,除非是传递资源采用release,Ps:血的教训。
release可以被调用无数次,如果不想计数一直累加,可以使用有界信号量BoundedSemaphore。
2.运用
2.1.线程间传递数据
线程A向线程B传递数据,线程B一直acquire,每次线程A release之前,无需要acquire,线程B acquire之后取到数据,也无需要release,否则线程B acquire会一直被触发,消耗CPU,如1中注意项所说。
class C(threading.Thread):
def __init__(self):
self.queue = queue.Queue(128)
self.sem = threading.Semaphore()
super().__init__()
def run(self):
self.sem.acquire()
self.queue.get()
...
def func():
c = C()
c.queue.put(data)
c.sem.release()
...
2.2.多线程信号量
使用信号量控制多线程,在线程1启动后,调用acquire一次,sem计数-1,为0,其他线程将会阻塞,线程1调用release后,sem计数+1,其他线程中某一线程会被触发,接着调用release,其他线程相继执行完成。
...
def funcA(i, sem):
sem.acquire()
...
sem.release()
...
if(__name__ == "__main__"):
sem = threading.Semaphore(3)
for i in rang(3):
thread = threading.Thread(target=run, args=(i,sem))
thread.start()
...
总结
信号量是由系统管理提供的抽象数据类型,用于多线程间资源同步。
参考
https://blog.csdn.net/weixin_28718793/article/details/114953067
https://blog.csdn.net/weixin_47021806/article/details/115535520