关于 Python 多线程的一个疑问,见笑!

2019-07-25 15:19:02 +08:00
 xianhu
既然 Python 的多线程模式是伪多线程,即同一时刻只能有一个线程执行。那么为什么还会有 threading.Queue 这种所谓线程安全的变量类型呢?我理解应该任何数据类型( list、tuple 等)都是线程安全的。
有谁可以给解释一下吗?
3412 次点击
所在节点    Python
25 条回复
cigarzh
2019-07-25 16:45:35 +08:00
i += 1
xianhu
2019-07-25 16:58:45 +08:00
@cigarzh 感谢。通过一通试验之后,我貌似明白了。
CEBBCAT
2019-07-25 17:02:25 +08:00
原子操作吗? 看了前两楼还是没太懂
ctrlaltdeletel
2019-07-25 17:09:52 +08:00
同一时刻只能有一个线程执行指的是 byte code 级别的执行,一个包含多个 byte code 的函数中仍有可能会发生线程调度的
jingxyy
2019-07-25 17:14:30 +08:00
就是原子性问题呗 虽然有 gil 但你想象一个场景 比如你对 list 做 append append 要做好几个操作 某个线程做了一部分的操作 然后切到另一个线程再做 append 这会有啥后果
bantao
2019-07-25 17:15:10 +08:00
cpu 支持并发,达到某些条件会线程切换,Python 因为 GIL 而不支持真正的并行,GIL 同一时刻( cpu 时间片)只允许一个线程,不是在一段时间内只允许一个线程执行。所以线程不安全的变量,在多线程环境中,可能在变量并未发生变化时,就被切换到另外一个线程中被使用了。https://www.zhihu.com/question/23030421
xianhu
2019-07-25 17:26:10 +08:00
@jingxyy 真巧,针对这个场景,我刚刚用代码跑了一下 [启动 4 个线程,一个全局的 list 变量,每个线程都对这个 list 进行 append 操作 100000 次] 。跑完之后,对于这个 list 的长度没什么影响,里边的元素值也没什么影响,只是对元素的排列顺序有影响。
xianhu
2019-07-25 17:33:26 +08:00
@xianhu 把这个实验中的 list 改为一个 int 值,每个线程对这个值进行+1 操作 100000 次,最终查看结果,发现值对不上。这就是 1 楼 i += 1 的意思。
jingxyy
2019-07-25 18:01:02 +08:00
@xianhu
这样吗(翻车了……
回头看看 list 底层有什么魔法
wwqgtxx
2019-07-25 20:37:02 +08:00
@jingxyy @xianhu python 官方文档提到了在 cpython 的实现中 list 的 append 是原子的
https://docs.python.org/3.7/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe
wwqgtxx
2019-07-25 20:41:21 +08:00
其实一个操作是不是原子的有两种评判标准:
1、对于纯 Python 代码,是不是只有一条 byte code
2、对于 C 实现的函数,内部有没有释放 GIL
hhhsuan
2019-07-25 20:43:01 +08:00
忘了 Python 线程吧,直接用进程
whoami9894
2019-07-25 21:02:01 +08:00
@hhhsuan 不是 CPU 密集运算干嘛用多进程? I/O 操作的单核线程并发相比进程开销要高效的多
Hopetree
2019-07-25 22:17:00 +08:00
@hhhsuan 你用过 python 吗?知道什么时候用线程什么时候用进程吗?不知道就别乱说
还有,那些喜欢拿 python 的 GIL 说事情的人麻烦好好看看自己的代码有没有资格被 GIL 影响
wwqgtxx
2019-07-25 23:21:36 +08:00
@hhhsuan 多进程来传递个 FD 看能不能把你搞疯掉
bilibilifi
2019-07-26 05:58:16 +08:00
@whoami9894 感觉 python 的 multprocessing 确实有黑科技,试过把主 loop 用 prange 重写只快了百分之 30
jingxyy
2019-07-26 08:53:12 +08:00
@wwqgtxx
原来如此 感谢
oahebky
2019-07-26 08:53:58 +08:00
用 C 语言写的多线程在十几二十年前的单核 CPU 的电脑上运行,需不需要保证线程安全呢???
(同理,用其它语言写多线程在单核 CPU 上运行需不需要保证线程安全呢?)

现在搞不清楚也没关系,多看书,看看名校公开课,写写代码,逐渐就有概念了。
cwjokaka
2019-07-26 10:02:51 +08:00
因为多线程之间会进行上下文切换,执行非原子操作的时候可能在过程中挂起当前线程,之后继续执行的的时数据可能已不是最新了
xianhu
2019-07-26 10:22:29 +08:00
@wwqgtxx 感谢。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/586149

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX