栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python并行编程(三):多线程同步之semaphore(信号量)实现简易生产者-消费者模型

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python并行编程(三):多线程同步之semaphore(信号量)实现简易生产者-消费者模型

什么是信号量

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)

简易生产者-消费者模型

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.')

运行截图如下:

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号