1. 使用条件进行线程同步
条件指的是应用程序状态的改变。这是另一种同步机制,其中某些线程在等待某一条件发生,其他的线程会在该条件发生的时候进行通知。一旦条件发生,线程会拿到共享资源的唯一权限。
解释条件机制最好的例子还是生产者-消费者问题。在本示例中,只要缓存不满,生产者一直向缓存生产;只要缓存不空,消费者一直从缓存取出(之后销毁)。当缓冲队列不为空的时候,生产者将通知消费者;当缓冲队列不满的时候,消费者将通知生产者。
#!/usr/bin/python3
#!--*-- coding:utf-8 --*--
from threading import Thread, Condition
import time
items = []
condition = Condition()
class consumer(Thread):
def __init__(self):
Thread.__init__(self)
def consume(self):
global condition
global items
condition.acquire() #消费者通过拿到锁来修改共享的资源 items[]
if len(items) == 0: #如果list的长度为0,那么消费者就进入等待状态
condition.wait()
print("Consumer notify : no item to consume")
items.pop() #通过 pop 操作消费一个item
print("Consumer notify : consumed 1 item")
print("Consumer notify : items to consume are " + str(len(items)))
#消费者的状态被通知给生产者,同时共享资源释放
condition.notify()
condition.release()
def run(self):
for i in range(0, 20):
time.sleep(2)
self.consume()
class producer(Thread):
def __init__(self):
Thread.__init__(self)
def produce(self):
global condition
global items
#生产者拿到共享资源,然后确认缓冲队列是否已满
#这里,缓冲队列最大可以存放10个item
condition.acquire()
if len(items) == 10:#如果已经满了,那么生产者进入等待状态,直到被唤醒
condition.wait()
print("Producer notify : items producted are " + str(len(items)))
print("Producer notify : stop the production!!")
items.append(1)
print("Producer notify : total items producted " + str(len(items)))
#如果队列没有满,就生产1个item,通知状态并释放资源
condition.notify()
condition.release()
def run(self):
for i in range(0, 20):
time.sleep(1)
self.produce()
if __name__ == "__main__":
producer = producer()
consumer = consumer()
producer.start()
consumer.start()
producer.join()
consumer.join()
如,
2. 使用事件进行线程同步
事件是线程之间用于通讯的对象。有的线程等待信号,有的线程发出信号。基本上事件对象都会维护一个内部变量,可以通过 set()
方法设置为 true
,也可以通过 clear()
方法设置为 false
。 wait()
方法将会阻塞线程,直到内部变量为 true
。
#!/usr/bin/python3
#!--*-- coding: utf-8 --*--
import time
from threading import Thread, Event
import random
items = []
event = Event()
class consumer(Thread):
def __init__(self, items, event):
Thread.__init__(self)
self.items = items
self.event = event
def run(self):
while True:
time.sleep(2)
self.event.wait()
item = self.items.pop()
print('Consumer notify : %d popped from list by %s' % (item, self.name))
class producer(Thread):
def __init__(self, items, event):
Thread.__init__(self)
self.items = items
self.event = event
def run(self):
global item
for i in range(100):
time.sleep(2)
item = random.randint(0, 256)
self.items.append(item)
print('Producer notify : item N° %d appended to list by %s' % (item, self.name))
print('Producer notify : event set by %s' % self.name)
self.event.set()
print('Produce notify : event cleared by %s '% self.name)
self.event.clear()
if __name__ == '__main__':
t1 = producer(items, event)
t2 = consumer(items, event)
t1.start()
t2.start()
t1.join()
t2.join()
生产者和消费者认识: