我们可以看到这个函数用 Python 的标准 dis 模块编译的字节码:
- >>> import dis
- >>> dis.dis(foo)
- LOAD_GLOBAL 0 (n)
- LOAD_CONST 1 (1)
- INPLACE_ADD
- STORE_GLOBAL 0 (n)
代码的一行中, n += 1,被编译成 4 个字节码,进行 4 个根本操作:
- 将 n 值加载到客栈上
- 将常数 1 加载到客栈上
- 将客栈顶部的两个值相加
- 将总和存储回 n
记住,一个线程每运行 1000 字节码,就会被说冥器打断夺走 GIL 。如不雅命运运限不好,这(打断)可能产生在线程加载 n 值到客栈时代,以及把它存储回 n 时代。很轻易可以看到这个过程会若何导致更新损掉:
在一个法度榜样员具备的所有特点中,想商量事物运转规律的┞封种好奇心必弗成少。当我打开音乐盒,不雅察内部装配,可以看出即使我没有成长为一个卓越的法度榜样员,至少也是有好奇心的一个。
- threads = []
- for i in range(100):
- t = threading.Thread(target=foo)
- threads.append(t)
- for t in threads:
- t.start()
- for t in threads:
- t.join()
- print(n)
平日这个代码输出 100,因为 100 个线程每个都递增 n 。但有时你会看到 99 或 98 ,如不雅一个线程的更新被另一个覆盖。
- n = 0
- lock = threading.Lock()
- def foo():
- global n
- with lock:
- n += 1
如不雅我们应用一个原子操作比如 sort() 函数会若何呢?:
- lst = [4, 1, 3, 2]
- def foo():
- lst.sort()
这个函数的字节码显示 sort() 函数不克不及被中断,因为它是原子的:
- >>> dis.dis(foo)
- LOAD_GLOBAL 0 (lst)
- LOAD_ATTR 1 (sort)
- CALL_FUNCTION 0
推荐阅读
中断产生,并由中断导致的宕机,将导致云用户的收入受损。这些故障也可能对企业的荣誉产生晦气影响,即使问题已经解决了几个礼拜或几个月。比拟于本地基本架构,公有云计算平日会削减企业>>>详细阅读
本文标题:深入理解GIL:如何写出高性能及线程安全的Python代码
地址:http://www.17bianji.com/lsqh/35440.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示