2022年 11月 3日

python信号量_Python信号量

Python信号量教程

信号量是由操作系统管理的一种抽象数据类型,用于在多线程中同步对共享资源的使用。本质上说,信号量是一个内部数据,用于标明当前的共享资源可以有多少并发读取。

也可以简单的理解为,信号量是多把锁,同时允许多个线程来更改数据,而

Python信号量与互斥锁的关系

信号量的一个特殊用法是互斥量。互斥量是初始值为 1 的信号量,可以实现数据、资源的互斥访问。

Python信号量使用详解

语法

import threading

sem = threading.Semaphore(3)

sem.acquire()

sem.release()

说明

首先,我们需要使用 threading.Semaphore 创建一个信号量的实例,创建实例时,需要指定一个 value

接着,在我们对临界资源进行访问的时候,调用 acquire(),此时内置计数器 -1,直到为 0 的时候就阻塞。资源调用完毕后调用 release(),内置计数器 +1,并让某个线程的 acquire() 从阻塞变为不阻塞。

案例

Python多线程信号量使用

使用 threading.Semaphore 信号量控制多线程

import threading

import time

def run(n):

semaphore.acquire()

time.sleep(1)

print(“thread:%s is running” % n)

semaphore.release()

if __name__ == ‘__main__’:

print(“嗨客网(www.haicoder.net)”)

semaphore = threading.Semaphore(3) #最多允许3个线程同时运行

for i in range(3):

t = threading.Thread(target=run, args=(i,))

t.start()

while threading.active_count() != 1:

pass

else:

print(‘—-all threads done—‘)

程序运行后,控制台输出如下:

91d21c8437bf2882ec05d20ce37deb83.png

我们在

接着,我们使用

从运行结果来看,我们的线程的确是并发执行的,理论上三个线程完全可以同时运行,最后的

Python多线程信号量使用

使用 threading.Semaphore 信号量控制多线程

import threading

import time

class htmlSpider(threading.Thread):

def __init__(self, url, sem):

super().__init__()

self.url = url

self.sem = sem

def run(self):

time.sleep(2)

print(“got haicoder text success”)

self.sem.release() # 内部维护的计数器加1,并通知内部维护的conditon通知acquire

class UrlProducer(threading.Thread):

def __init__(self, sem):

super().__init__()

self.sem = sem

def run(self):

for i in range(20):

self.sem.acquire() # 内部维护的计数器减1,到0就会阻塞

html_thread = htmlSpider(“http://www.haicoder.net/{}”.format(i), self.sem)

html_thread.start()

if __name__ == “__main__”:

print(“嗨客网(www.haicoder.net)”)

sem = threading.Semaphore(3) #设置同时最多3个

url_producer = UrlProducer(sem)

url_producer.start()

程序运行后,控制台输出如下:

75fc6338fb89d7b530b3f99b9b0b6445.png

我们在 main 函数中,首先使用了 threading.Semaphore 创建了一个信号量,同时,传入了参数 3,即最多允许 3 个线程同时并发的执行。接着,我们创建了一个 UrlProducer 线程,用来模拟爬取 url,同时在 UrlProducer 线程里,我们使用 for 循环一次性开启了 20 个 htmlSpider 线程,用来模拟爬取 url 对应的网页。

这里,如果我们直接开 20 个 htmlSpider 线程,20 个线程是同时执行的,可能会造成服务器的压力过大,所以我们为了限制一次性最多只允许 3 个线程同时爬取,这里在每开启一个线程 htmlSpider 之前,我们都使用 acquire() 函数获取一个资源,每次 htmlSpider 线程运行结束,我们使用 release() 函数,释放资源。

从运行结果来看,我们的线程的确是并发执行的,理论上三个线程完全可以同时运行,因此,在这里,我们通过信号量实现了模拟控制爬虫的线程数的场景。

Python信号量教程总结

信号量是由操作系统管理的一种抽象数据类型,用于在多线程中同步对共享资源的使用。本质上说,信号量是一个内部数据,用于标明当前的共享资源可以有多少并发读取。

也可以简单的理解为,信号量是多把锁,同时允许多个线程来更改数据,而互斥锁同时只允许一个线程更改数据。Python信号量使用语法:

import threading

sem = threading.Semaphore(3)

sem.acquire()

sem.release()