欢迎大家来到IT世界,在知识的湖畔探索吧!
15.jpg
什么是信号量
semaphore信号量,其控制着对公共资源或者临界区的访问。信号量维护着一个计数器,指定可同时访问资源或者进入临界区的线程数。
semaphore是一个内置的计数器
每当调用acquire()时,内置计数器-1;如果计数器为负数,即资源正在被占用,需要挂起等待
每当调用release()时,内置计数器+1;增加到正数时,队列中的第一个等待线程就可以访问共享资源了
模拟Lock()锁机制
如果我们将计数器设置为1即,第一次线程是不需要等待信号量的释放的,参照上节代码可以进行对比:
import threading import time resoure = 0 count = 1000000 semaphore = threading.Semaphore(1) def increment(): global resoure for i in range(count): semaphore.acquire() resoure += 1 semaphore.release() def decerment(): global resoure for i in range(count): semaphore.acquire() resoure -= 1 semaphore.release() increment_thread = threading.Thread(target=increment) decerment_thread = threading.Thread(target=decerment) increment_thread.start() decerment_thread.start() increment_thread.join() decerment_thread.join() print(resoure)
欢迎大家来到IT世界,在知识的湖畔探索吧!
简易生产者-消费者模型
欢迎大家来到IT世界,在知识的湖畔探索吧!import threading import random import time semaphore = threading.Semaphore(0) # 假设生产的资源 item_number = 0 # 消费者 def consumer(): print('Consumer is waiting for Producer') # 等待获取信号量 semaphore.acquire() print('get the product , number is {}'.format(item_number)) # 生产者 def producer(): global item_number # 模拟生产资源过程 time.sleep(2) item_number = random.randint(1, 100) time.sleep(2) print('made the product , number is {}'.format(item_number)) # 释放信号量 semaphore.release() if __name__ == "__main__": for i in range(5): # 将生产者、消费者实例化为线程 thread_consumer = threading.Thread(target=consumer) thread_producer = threading.Thread(target=producer) thread_consumer.start() thread_producer.start() thread_consumer.join() thread_producer.join() print('consumer-producer example end.')
运行截图如下:
运行结果
我们可以看见两个线程运行时的规律,即消费者必须等待生产者生产好商品(即释放资源),消费者才能获取消费资源(即访问资源),其余时间消费者线程都处于挂起等待(等待信号量)。利用信号量控制并发数量
利用semaphore我们就可以设置同时访问某些共享资源的线程数量,即通过设设置信号量的值来控制线程同时访问的数量,比如我们可以控制爬虫程序访问链接的线程数量(似乎这样可以实现一定的异步),减少目标网站的压力,同时信号量也支持上下文管理器:
import threading import random import time # 信号量为三即能够释放的资源为三次 semaphore = threading.Semaphore(3) # 互斥锁+队列 相当于一个容器,容器里同时最大可以存在五个钥匙,同时也只能有五个线程, # 谁先拿到并释放后,下一个才能拿到钥匙 # 假定url序号 order = 0 def spider(): global order with semaphore: # 模拟采集过程 time.sleep(2) order +=1 print('{} is crawlering on {}th url'.format(threading.currentThread().getName(), order)) time.sleep(2) Threads = [] for i in range(10): t = threading.Thread(target=spider) Threads.append(t) t.start() for t in Threads: t.join() print('Spider end.')
运行截图如下:
运行结果
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/17445.html