Python3 threading Semaphore 信号量

来谈一谈Semaphore,它内部维护了一个计数器,每一次acquire操作都会让计数器减1,每一次release操作都会让计数器加1,当计数器为0时,任何线程的acquire操作都不会成功,Semaphore确保对资源的访问有一个上限。

如果使用Lock,RLock,那么只能有一个线程获得对资源的访问,但现实中的问题并不总是这样,假设这样一个场景,一个线程安全的操作,同一个时刻可以允许两个线程进行,如果太多了效率会降低,那么Lock,Rlock,包括Condition就不适合这种场景。

我这里举一个不恰当的例子(因为我自己没这么干过,但有助于你理解)。假设你写了一个多线程爬虫,起10个线程去爬页面,10个线程访问过于频繁了,目标网站对你采取反爬措施。但你把线程数量降到2两个就没问题了。那么对于这个场景,你仍然可以启动10个线程,只是向目标网站发送请求的这个操作,你可以用Semaphore来控制,使得同一个时刻只有两个线程在请求页面

Python
# coding=utf-8 import <span class="wp_keywordlink_affiliate"><a href="https://www.168seo.cn/tag/threading" title="View all posts in threading" target="_blank">threading</a></span> import time semaphore = <span class="wp_keywordlink_affiliate"><a href="https://www.168seo.cn/tag/threading" title="View all posts in threading" target="_blank">threading</a></span>.Semaphore(2) def worker(id): print 'thread {id} acquire semaphore'.format(id=id) semaphore.acquire() print 'thread {id} get semaphore do something'.format(id=id) time.sleep(2) semaphore.release() print 'thread {id} release semaphore'.format(id=id) for i in range(10): t = <span class="wp_keywordlink_affiliate"><a href="https://www.168seo.cn/tag/threading" title="View all posts in threading" target="_blank">threading</a></span>.Thread(target=worker, args=(i, )) t.start()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# coding=utf-8
import threading
import time
semaphore = threading . Semaphore ( 2 )
 
 
def worker ( id ) :
     print 'thread {id} acquire semaphore' . format ( id = id )
     semaphore . acquire ( )
     print 'thread {id} get semaphore do something' . format ( id = id )
     time . sleep ( 2 )
     semaphore . release ( )
     print 'thread {id} release semaphore' . format ( id = id )
 
 
for i in range ( 10 ) :
     t = threading . Thread ( target = worker , args = ( i , ) )
     t . start ( )

也可以用到 比如限制数据库的链接数量




  • zeropython 微信公众号 5868037 QQ号 5868037@qq.com QQ邮箱
### Python多线程同步中的信号量机制 在Python中,`threading`模块提供了一个名为`Semaphore`的类来实现信号量机制。信号量是一种用于控制多个线程对共享资源访问的同步原语[^1]。 #### 什么是信号量信号量是一个计数器,表示可用资源的数量。它允许多个线程同时访问某些受限资源,而不会导致竞争条件或数据不一致的情况发生[^2]。通常情况下,信号量被用来解决生产者-消费者问题或其他涉及并发访问有限资源的问题。 #### `Semaphore` 类的核心功能 `Semaphore`类的主要方法包括: - **acquire()**: 减少信号量计数值(即获取一个许可)。如果当前计数值大于零,则立即返回;否则阻塞直到有可用的许可。 - **release()**: 增加信号量计数值(即释放一个许可),从而允许其他等待的线程继续执行。 下面展示如何使用`Semaphore`来进行基本的线程同步: ```python import threading import time class WorkerThread(threading.Thread): def run(self): print(f"{self.name} is trying to acquire the semaphore.") with semaphore: # 自动处理acquire和release print(f"{self.name} has acquired the semaphore.") time.sleep(2) # Simulate some work being done. print(f"{self.name} is releasing the semaphore.") if __name__ == "__main__": semaphore = threading.Semaphore(3) # 创建一个最多允许三个线程同时进入临界区的信号量 threads = [] for i in range(5): # 创建五个线程 thread = WorkerThread() threads.append(thread) thread.start() for t in threads: t.join() # 主线程等待所有子线程完成 ``` 在这个例子中,我们创建了一个只允许三个线程同时运行的任务环境。当第四个或第五个线程尝试获得信号量时,它们会被挂起直至前几个线程释放其持有的信号量[^4]。 #### BoundedSemaphore 的特殊用途 除了普通的`Semaphore`外,还有另一种叫做`BoundedSemaphore`的对象。这种类型的信号量会检查是否有过多的`release()`操作被执行,并抛出异常以防止错误的发生[^3]。 以下是带有边界保护的一个简单示例: ```python bounded_semaphore = threading.BoundedSemaphore(value=2) def bounded_worker(): try: bounded_semaphore.acquire() print("Resource accessed by", threading.current_thread().getName()) time.sleep(1) finally: bounded_semaphore.release() for _ in range(4): threading.Thread(target=bounded_worker).start() ``` 这里展示了即使多次调用了`release()`也不会造成逻辑混乱的安全保障措施。 #### 总结 通过上述讨论可以看出,在Python里利用`threading.Semaphore`能够有效地协调多个线程之间的协作关系,尤其是在那些需要限制同一时刻可活动线程数目的情形下显得尤为重要[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值