参考博客:
https://segmentfault.com/a/1190000008123688 (以图的方式解释了lock锁、rlock锁、semaphore信号量)
http://blog.sina.com.cn/s/blog_82fefc100102xg97.html (以semaphore信号量实现了生产者消费者)
https://blog.csdn.net/qq_33371343/article/details/79201161 (解释了semaphore信号量中信号量的功能)
https://www.jianshu.com/p/e52154188acc (以实际semaphore的代码展示了如何允许指定数量的线程同时运行)
http://www.manongjc.com/detail/15-tdstifzseqcxlaw.html (介绍了semaphore信号量和BoundedSemaphore有界信号量的区别)
初始印象:
简单点说,Semphore,是一种带计数的线程同步机制,当调用release时,增加计数,当acquire时,减少计数,当计数为0时,自动阻塞,等待release被调用。
什么时候被使用:
import time
import threading
def foo():
time.sleep(2) #程序休息2秒
print("ok",time.ctime())
for i in range(20):
t1=threading.Thread(target=foo,args=()) #实例化一个线程
t1.start() #启动线程
输出:
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
ok Tue Jul 18 20:05:58 2017
可以看到,程序会在很短的时间内生成20个线程来打印一句话,如果在主机执行IO密集型任务的时候再执行这种类型的程序时,计算机就有很大可能会宕机。 这时候就可以为这段程序添加一个计数器功能,来限制一个时间点内的线程数量。
使用方法:指定数量的线程同时运行:
# -*- coding:utf-8 -*-
import threading
import time
sem = threading.Semaphore(3)
class DemoThread(threading.Thread):
def run(self):
print('{0} is waiting semaphore.'.format(self.name))
sem.acquire()
print('{0} acquired semaphore({1}).'.format(self.name, time.ctime()))
time.sleep(5)
print('{0} release semaphore.'.format(self.name))
sem.release()
if __name__ == '__main__':
threads = []
for i in range(4):
threads.append(DemoThread(name='Thread-' + str(i)))
for t in threads:
t.start()
for t in threads:
t.join()
结果:
Thread-0 is waiting semaphore.
Thread-0 acquired semaphore(Thu Oct 25 20:33:18 2018).
Thread-1 is waiting semaphore.
Thread-1 acquired semaphore(Thu Oct 25 20:33:18 2018).
Thread-2 is waiting semaphore.
Thread-2 acquired semaphore(Thu Oct 25 20:33:18 2018).
Thread-3 is waiting semaphore.
Thread-0 release semaphore.
Thread-3 acquired semaphore(Thu Oct 25 20:33:23 2018).
Thread-1 release semaphore.
Thread-2 release semaphore.
Thread-3 release semaphore.
有界信号量boundageSamephore:
BoundedSemaphore在调用release()的时候,会校验一下当前信号量的值,是否会大于初始值(只定义了5个信号量,释放了5次后,还要调用release)的场景,会抛出异常,而 Semaphore在这种场景下,release()的结果只是None,没有返回信号量对象,并不会抛出异常。
具体例子:
import threading
#sem=threading.BoundedSemaphore(5)
sem=threading.Semaphore(5)
global num
num=0
def run():
global num
sem.acquire()
num+=1
if num>0:
sem.release()
print(sem.release())
for i in range(20):
threading.Thread(target=run,args=()).start()
print(num)