线程进程协程和GIL
Posted ss-py
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程进程协程和GIL相关的知识,希望对你有一定的参考价值。
上一篇文章介绍了:创建县城的两种方式、Event对象判断线程是否启动、利用信号量控制线程并发。
博客链接:线程、进程、协程和GIL(二)
这一篇来说说线程间通信的那些事儿:
一个线程向另一个线程发送数据最安全的方式就是使用queue库中的队列了,通过创建一个供多个线程共享的Queue对象,这些线程使用put()和get()操作来向队列中添加数据或者从队列中取出数据,以达到线程间通信的效果。
queue队列基本方法:
queue.Queue(maxsize = num): FIFO 先进先出队列,如果maxsize小于或等于0 则代表队列长度无线。
queue.LifoQueue(maxsize = num): LIFO 后进先出队列(类似于栈),如果maxsize小于或等于0 则代表队列长度无线。
Queue.qsize(): 返回当前队列中元素的个数
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.get([block[, timeout]]) 读队列,timeout等待时间
Queue.put(item, [block[, timeout]]) 写队列,timeout等待时间
Queue.queue.clear() 清空队列
使用Queue构造生产者消费者模型来实现线程间的通信:
import time from queue import Queue,LifoQueue from threading import Thread def producer(in_q): while True: time.sleep(1) data = ‘包子‘ if in_q.full() == True: print(‘蒸笼满了,放不下了‘) in_q.put(data) # 向队列中塞东西 print(‘小明蒸%s!‘ %(data)) def customer(out_q): while True: time.sleep(3) if out_q.empty() == True: print(‘小红没取到包子,饿死了!‘) data = out_q.get() # 从队列中取东西 print(‘小红取 %s ‘ % (data)) if __name__ == ‘__main__‘: q = Queue(maxsize=3) t1 = Thread(target=producer, args=(q,)) t2 = Thread(target=customer, args=(q,)) t1.start() t2.start()
上面的代码实现了一个简单的生产者消费者,小明负责蒸包子,小红负责吃包子。当队列被包子塞满时,小明就再也放不进去了,此时生产者这个线程就会阻塞。当小红将队列中的包子吃完时,消费者这个线程就会阻塞。因为Queue对象已经封装了必要的锁,所以我们可以在多个线程之间安全的功能共享数据。
但是在生产者消费者的关闭问题会有一些麻烦,通用的解决方式就是在队列中放置一个特殊值,当消费者读到这个值时,就终止执行:
以上是关于线程进程协程和GIL的主要内容,如果未能解决你的问题,请参考以下文章