条件变量同步
有一类线程需要满足条件之后才能够继续执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock()的方法外,还提供了 wait()、notify()、notifyAll()方法。 lock_con=threading.Condition([Lock/Rlock]): 锁是可选选项,不传人锁,对象自动创建一个RLock()。
1wait():条件不满足时调用,线程会释放锁并进入等待阻塞; 2notify():条件创造后调用,通知等待池激活一个线程; 3notifyAll():条件创造后调用,通知等待池激活所有线程。 4 5 6import threading, time 7from random import randint 8 9class Producer(threading.Thread): 10 def run(self): 11 global L 12 while True: 13 val = randint(0, 100) 14 print('生产者', self.name, ':Append'+str(val),L) 15 if lock_con.acquire(): 16 L.append(val) 17 lock_con.notify() 18 lock_con.release() 19 time.sleep(3) 20 21class Consumer(threading.Thread): 22 def run(self): 23 global L 24 while True: 25 lock_con.acquire() 26 if len(L) == 0: 27 lock_con.wait() 28 print('消费者', self.name, ":Delete" + str(L[0]), L) 29 del L[0] 30 lock_con.release() 31 time.sleep(0.25) 32 33 34if __name__ == "__main__": 35 L = [] 36 lock_con = threading.Condition() 37 threads = [] 38 for i in range(5): 39 threads.append(Producer()) 40 threads.append(Consumer()) 41 for t in threads: 42 t.start() 43 for t in threads: 44 t.join() 45 print('---- end ----') 46 47#运行结果: 48生产者 Thread-1 :Append63 [] 49生产者 Thread-2 :Append66 [63] 50生产者 Thread-3 :Append20 [63, 66] 51生产者 Thread-4 :Append83 [63, 66, 20] 52生产者 Thread-5 :Append2 [63, 66, 20, 83] 53生产者 Thread-4 :Append26 [] 54消费者 Thread-6 :Delete26 [26] 55生产者 Thread-2 :Append21 [] 56生产者 Thread-3 :Append71 [21] 57生产者 Thread-1 :Append19 [21, 71] 58生产者 Thread-5 :Append100 [21, 71, 19] 59生产者 Thread-1 :Append96 [] 60消费者 Thread-6 :Delete96 [96] 61........ 62
同步条件
条件同步和条件变量同步差不多意思,只是少了锁功能,因为条件同步设计于不访问共享资源的条件环境。event=threading.Event():条件环境对象,初始值 为False;
1event.isSet():返回event的状态值; 2event.wait():如果 event.isSet()==False将阻塞线程; 3event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度; 4event.clear():恢复event的状态值为False。 5 6 7import threading, time 8 9class Boss(threading.Thread): 10 def run(self): 11 print("BOSS: 今晚大家加班") 12 event.isSet() or event.set() 13 time.sleep(5) 14 print("BOSS: 大家可以下班了") 15 event.isSet() or event.set() 16 17 18class Worker(threading.Thread): 19 def run(self): 20 event.wait() 21 print("Worker: 唉。。。。") 22 time.sleep(0.25) 23 event.clear() 24 event.wait() 25 print("Worker: Great!") 26 27 28if __name__ == "__main__": 29 event = threading.Event() 30 threads = [] 31 for i in range(5): 32 threads.append(Worker()) 33 threads.append(Boss()) 34 for t in threads: 35 t.start() 36 for t in threads: 37 t.join() 38 39#运行结果: 40BOSS: 今晚大家加班 41Worker: 唉。。。。 42Worker: 唉。。。。 43Worker: 唉。。。。 44Worker: 唉。。。。 45Worker: 唉。。。。 46BOSS: 大家可以下班了 47Worker: Great! 48Worker: Great! 49Worker: Great! 50Worker: Great! 51Worker: Great!
列队
1q = Queue.Queue(maxsize = 10) 创建一个“队列”对象。Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。 2 3q.put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。 4 5q.get([block[, timeout]])方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常,timeout等待时间。 6 7q.qsize() 返回队列的大小 8q.empty() 如果队列为空,返回True,反之False 9q.full() 如果队列满了,返回True,反之False 10q.full 与 maxsize 大小对应 11q.get_nowait() 相当q.get(False) 12q.put_nowait(item) 相当q.put(item, False) 13q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号 14q.join() 实际上意味着等到队列为空,再执行别的操作 15 16 17import queue 18 19d = queue.Queue() 20 21d.put('1') 22d.put('2') 23d.put('3') 24 25print(d.get()) 26print(d.get()) 27print(d.get()) 28print(d.get()) 29print(d.get(0)) 30 31# 运行结果: 321 332 343 35报错: 36queue.Empty
线程操作列表是不安全的。
1import threading, time 2 3li = [1, 2, 3, 4, 5] 4 5def pri(): 6 while li: 7 a = li [-1] 8 print(a) 9 time.sleep(1) 10 try: 11 li.remove(a) 12 except: 13 print('-----', a) 14t1 = threading.Thread(target=pri, args=()) 15t1.start() 16t2 = threading.Thread(target=pri, args=()) 17t2.start() 18 19# 运行结果: 205 215 224 23----- 5 244 253 26----- 4 273 282 29----- 3 302 311 32----- 2 331 34----- 1 35 36 37import threading, queue 38from time import sleep 39from random import randint 40 41class Production(threading.Thread): 42 def run(self): 43 while True: 44 r = randint(0, 100) 45 q.put(r) 46 print("生产出来 %s 号包子" %r) 47 sleep(1) 48 49class Proces(threading.Thread): 50 def run(self): 51 while True: 52 re = q.get() 53 print('吃掉 %s号包子' %re) 54 55if __name__ == '__main__': 56 q = queue.Queue(10) 57 threads = [Production(),Production(),Production(),Proces()] 58 for t in threads: 59 t.start() 60 61# 运行结果: 62生产出来 94 号包子 63生产出来 13 号包子 64生产出来 79 号包子 65吃掉 94号包子 66吃掉 13号包子 67吃掉 79号包子 68生产出来 43 号包子 69吃掉 43号包子 70生产出来 32 号包子 71吃掉 32号包子 72......