Queue类是线程安全的,适用于多线程间安全的交换数据。内部使用了Lock和Condition。
Queue类的size虽然加了锁,但是,依然不能保证立即get、put就能成功,因为读取大小和get、put方法是分开的。
import queue q = queue.Queue(8) if q.qsize() == 7: q.put() # 上下两句可能被打断 if q.qsize() == 1: q.get() # 未必会成功CPython在解释器进程级别有一把锁,叫做GIL,即全局解释器锁。 GIL保证CPython进程中,只有一个线程执行字节码。甚至是在多核CPU的情况下,也只允许同时只能有一个CPU上运行该进程的一个线程。
CPython中IO密集型,某个线程阻塞,就会调度其他就绪线程; CPU密集型,当前线程可能会连续的获得GIL,导致其他线程几乎无法使用CPU。 在CPython中由于有GIL存在,IO密集型,使用多线程较为合算;CPU密集型,使用多进程,要绕开GIL。
import logging import datetime FORMAT = '%(thread)s --> %(message)s' logging.basicConfig(level=logging.INFO, format=FORMAT) start = datetime.datetime.now() def calc(): sum = 0 for _ in range(1000000): sum += 1 calc() calc() calc() calc() delta = (datetime.datetime.now() - start).total_seconds() logging.info(delta) 15460 --> 0.260867 import logging import datetime import threading FORMAT = '%(thread)s --> %(message)s' logging.basicConfig(level=logging.INFO, format=FORMAT) start = datetime.datetime.now() def calc(): sum = 0 for _ in range(1000000): sum += 1 t1 = threading.Thread(target=calc) t2 = threading.Thread(target=calc) t3 = threading.Thread(target=calc) t4 = threading.Thread(target=calc) t1.start() t2.start() t3.start() t4.start() t1.join() t2.join() t3.join() t4.join() delta = (datetime.datetime.now() - start).total_seconds() logging.info(delta) 15460 --> 0.263845