admin 管理员组

文章数量: 1087649

【Python】条件变量、信号变量、事件

条件变量、信号变量、事件

  • 信号量:信号量是用来解决线程同步和互斥的通用工具, 和互斥量类似, 信号量也可以用作于资源互斥访问, 但信号量没有所有者的概念,在应用上比互斥量更广泛,信号量比较简单, 不能解决优先级反转问题,但信号量是一种轻量级的对象,比互斥量小巧,灵活,因此在很多对互斥要求不严格的的系统中,经常使用信号量来管理互斥资源。
    通常sem_post()和sem_wait()函数对信号量进行加减操作从而解决线程的同步和互斥。
相关定义:

数据类型:sem_t

信号量的创建:sem_init()

信号量的销毁:sem_destroy(sem_t* sem, int pshared, unsigned value);

( 第一个参数是信号量指针,第二个参数表示是否在进程间共享的标志,第三个参数表示信号量的初值;)

信号量的加操作:sem_post();(调用一次加1)

信号量的减操作:sem_wait();阻塞版本(调用一次减1)

信号量的减操作:sem_trywait();非阻塞版本

当线程调用sem_wait()后,若信号量的值小于0则线程阻塞。只有其他线程在调用sem_post对信号量作加操作后并且其值大于等于0时,阻塞的线程才能继续运行。

案例:

车站有3个安检口,那么同时只能有3个人安检,别人来了,只能等着别人安检完才可以过。

import threading
import os, time# 一次只允许3个人同时过安检
semapshore = threading.BoundedSemaphore(3)def run(num):semapshore.acquire()  # 获得信号量的锁print(f'第{num}个人正在过安检')time.sleep(2)semapshore.release()  # 释放这把锁if __name__ == '__main__':# 创建子线程thread = []for i in range(100):t = threading.Thread(target=run, args=(i,))t.start()thread.append(t)for t in thread:t.join()print('主线程执行完毕')
  • 条件变量:条件变量(condition variable)是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待某个条件为真,而将自己挂起;另一个线程使的条件成立,并通知等待的线程继续。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
相关定义:

数据类型:pthread_cond_t;

初始化:pthread_cond_init();

销毁:pthread_cond_destroy();

条件变量等待操作:pthread_cond_wait();

带有超时的等待:pthread_cond_timewait();

条件变量的解除等待操作:pthread_cond_signal();——通知单个线程

条件变量的解除等待操作:pthread_cond_broadcast();——通知所有线程

案例:

假设有一群生产者(Producer)和一群消费者(Consumer)通过一个市场来交互产品。生产者的”策略“是如果市场上剩余的产品少于1000个,那么就生产100个产品放到市场上;而消费者的”策略“是如果市场上剩余产品的数量多余100个,那么就消费3个产品。用Condition解决生产者与消费者问题的代码如下:

import threading
import timeclass Producer(threading.Thread):
def run(self):
global count
while True:
if con.acquire():
if count > 1000:con.wait()
else:count = count+100msg = self.name+' produce 100, count=' + str(count)
print msgcon.notify()con.release()time.sleep(1)class Consumer(threading.Thread):
def run(self):
global count
while True:
if con.acquire():
if count < 100:con.wait()
else:count = count-3msg = self.name+' consume 3, count='+str(count)
print msgcon.notify()con.release()time.sleep(1)count = 500
con = threading.Condition()def test():
for i in range(2):p = Producer()p.start()
for i in range(5):c = Consumer()c.start()
if __name__ == '__main__':test()
  • 事件:事件是通过某一时刻某一个动作而触发的一个操作。事件的形成有两步:第一步是事件的预先定义;第二步事件触发。
事件触发案例:
#coding:utf-8
import  threadingevent  =  threading.Event()def  a():print ( "我是第一个线程函数a,我在等待函数b来触发我..." )event.wait()print ( "函数a说:尼玛!我被函数b给触发了..." )def  b():print ( "我是第二个线程函数b,我开始去触发函数a..." )event. set ()p  =  threading.Thread(target = a)
c  =  threading.Thread(target = b)p.start()
c.start()

本文标签: Python条件变量信号变量事件