原子性判断
在《关于Python GIL》里提到,默认情况下每隔100个tick强制释放一次GIL,相对于具体业务而言,这具有极强的随机性,因为你也不知道自己的代码在执行过程中什么时候就被释放了GIL。使用dis.dis
可以查看bytecode,我们默认一个bytecode(可能)具有原子性,即单bytecode的Python语句才(可能)有原子性。
之所以说可能有原子性,是指这条语句不会因每隔100个tick强制释放GIL的CPython默认行为失去原子性,但不能保证调用函数内部不会主动释放GIL,可以参考《关于Python GIL》中accept
的例子。
由此引发的思考是,仅用dis.dis
判断语句的bytecode数决定是否需要加锁,其实并不科学。
原子操作
对基本类型(包括list
或者dict
在内的容器)本身的操作是可以做到线程安全的,比如:
- 获取局部变量的值或对其赋值
- 获取全局变量的值或对其赋值
- 从
list
中取值 - 从
dict
中取值 - 对
list
的在位修改操作(比如append
) - 对
dict
的在位修改操作(比如增加元素)
获取元素的值,修改值,再写会并不是线程安全的,比如:
-
i = i + 1
# 先获取i的值,然后相加,再赋值 -
L.append(L[-1])
# 先获取L[-1]的值,然后再append到L中 -
L[i] = L[j]
# 先获取L[j]的值,再赋值给L[i] -
D[x] = D[x] + 1
先获取D[x]的值,然后相加,再赋值
综上,list
和dict
不是线程安全的。
网友评论