Python中哪些数据类型是线程安全的?

如题,就是字符串,列表,元组等数据类型是否线程安全。


Python中哪些数据类型是线程安全的?
14 回复

线程安全的是因为针对某一数据结构的所有操作都是线程安全的。
所以 list dict str int 都不是线程安全的。
但是有些数据结构的某些操作确实是安全的,比如 list.pop()


Python里线程安全的数据类型主要就是那些在底层用原子操作或者GIL保护的基本类型。

先说结论:Python中,intfloatstrtuplefrozenset这些不可变类型是线程安全的,而listdictset这些可变类型在多线程同时读写时不是线程安全的,除非你加锁。

详细解释一下:

  1. 不可变类型(比如intstrtuple)因为创建后不能修改,所以多个线程同时读取同一个对象是安全的。但注意,如果你在多线程中做“读取-计算-写入”这种复合操作(比如i += 1),即使int本身不可变,这个操作也不是原子的,需要加锁或者用threading.Lock
  2. 可变类型(比如listdictset)的单个方法调用(比如list.append())在CPython中由于GIL(全局解释器锁)的存在,通常是原子的,但多个方法调用组合在一起(比如先检查if key in dictdict[key] = value)就不是原子的,会出现竞态条件。
  3. 标准库里的queue.Queue是线程安全的,专门用来在多线程之间传递数据。

简单建议:多线程读写可变对象时记得加锁。

以我的理解 如果解释器用的是 CPython 由于 GIL 的存在 所有数据结构都是 thread safe 的

楼上的理解是错的


线程 AB 同时操作 list
list 的[0]初始值为 0

线程 A 操作 100 次
list[0]+=1
线程 B 操作 100 次
list[0]+=1

so …… GG

打脸总是来的那么快 (哭哭

懂了 (逃

只要不是一条指令,完成所有步骤有 GIL 也没用。。

同意 1L,修改共享变量的时候都要加锁。

我知道 quque 是线程安全的

是不是安全的只要的用 dis 模块看一下字节码就明白了。字节码的每一行就是一个原子操作,多线程切换就是原子操作为单位的,只要一个操作需两行字节码的就不是线程安全的。

为什么代码运行的结果是线程安全的…

把操作次数增加到十万次(如果不够增加到一百万次),就会发现不是线程安全的。

1 、list 自己是线程安全的,所以 list.pop(),list.append(),len(list) 等都是线程安全的;
2 、list 里面的数据不一定是线程安全的,比如 list[0] += 1 就不是线程安全的,这是因为 v += 1 本身就不是原子的,这和 list 无关,反之如果 v += 1 是原子的,那么 list[0] += 1 也是线程安全的;

dict 也是一样的,dict 的 pop,add 等操作都是线程安全的,这和 go 里面的 map 不一样

回到顶部