semaphore
信号量,其控制着对公共资源或者临界区的访问。信号量维护着一个计数器,指定可同时访问资源或者进入临界区的线程数。 semaphore是一个内置的计数器 每当调用acquire()时,内置计数器-1;若是计数器为负数,即资源正在被占用,须要挂起等待 每当调用release()时,内置计数器+1;增长到正数时,队列中的第一个等待线程就能够访问共享资源了python
若是咱们将计数器设置为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)
复制代码
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.')
复制代码
运行截图以下: app
利用semaphore
咱们就能够设置同时访问某些共享资源的线程数量,即经过设设置信号量的值来控制线程同时访问的数量,好比咱们能够控制爬虫程序访问连接的线程数量(彷佛这样能够实现必定的异步),减小目标网站的压力,同时信号量也支持上下文管理器:dom
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.')
复制代码
运行截图以下: 异步