python中的GIL
- GIL(Global Interpreter Lock),就是一个锁。
- Python中的一个线程对应于 C语言 中的一个线程。
- GIL使得同一时刻只有一个线程在一个cpu上执行字节码,无法将多个线程分配到多个cpu上进行同步运行。如果在单核cpu上,线程是并发运行,而不是并行。
首先,这样效率不高,但是看似也不会产生数据访问冲突的问题,毕竟同一时刻只有一个线程在一个核上运行嘛,然而:
sum = 0def add(): global sum for i in range(1000000): sum += 1def subtract(): global sum for i in range(1000000): sum -= 1import threadingadd_thread = threading.Thread(target=add)sub_thread = threading.Thread(target=subtract)add_thread.start()sub_thread.start()add_thread.join()sub_thread.join()print(sum)
如果按照上面的理解,线程间很安全,最后结果应该会是 0,运行三次代码的结果如下:
# result:# 358918# 718494# -162684
这说明两个线程并没有顺序异步执行。在一些特定的情况,GIL这把锁会被打开,一定程度上达到并行的效果。
GIL会根据线程执行的字节码行数以及时间片以及遇到 I/O 操作打开,所以Python的多线程对 I/O 密集型代码比较友好,比如,文件处理和网络爬虫。
多线程编程
线程模块
在Python3中提供了两个模块来使用线程_thread和threading,前者提供了低级别、原始的线程以及一个简单的锁,相比后者功能还是比较有限的,所以我们使用threading模块。
使用案例
直接使用Thread来实例化
import timeimport threadingdef learn(obj): print("learning {sth} started".format(sth=obj)) time.sleep(2) print("learning {sth} end".format(sth=obj))def play(obj): print("playing {sth} started".format(sth=obj)) time.sleep(4) print("playing {sth} end".format(sth=obj)) # 创建出两个线程对象learn_thread = threading.Thread(target=learn, args=("Python