详解Python多线程下的list


Posted in Python onJuly 03, 2020

list 是 Python 常用的几个基本数据类型之一.正常情况下我们会对 list 有增删改查的操作,显然易见不会有任何问题.那么如果我们试着在多线程下操作list 会有问题吗?

多线程下的 list

安全 or 不安全? 不安全!

通常我们说的线程安全是指针对某个数据结构的所有操作都是线程安全,在这种定义下,Python 常用的数据结构 list,dict,str 等都是线程不安全的

尽管多线程下的 list 是线程不安全的,但是在 append 的操作下是它又是线程安全的.

如何判断线程安全呢?

对于线程安全不安全,我们可以通过极端条件下去复现,从而得出结论。比如说判断 list 是否线程安全

import threading
import time

# 随意设置 count 的值,值越大错误抛出的越快
count = 1000
l = []

def add():
  for i in range(count):
    l.append(i)
    time.sleep(0.0001)

def remove():

  for i in range(count):
    l.remove(i)
    time.sleep(0.0001)


t1 = threading.Thread(target=add)
t2 = threading.Thread(target=remove)
t1.start()
t2.start()
t1.join()
t2.join()
print(l)

有时候一次运行并不一定就会出错,多次重试之后会出现类似下面的错误

详解Python多线程下的list

很显然这种操作方式不具有普适性,如果要是欧气太强,说不定会一直不出现异常。

那么出了这种方式,有没有比较简单有效的方法吗?答案是有的

dis

dis 库是 Python 自带的一个库,可以用来分析字节码。这里我们需要有这样的认识,字节码的每一行都是一个原子操作,多线程切换就是以原子操作为单位的,如果一个操作需要两行字节码就说明它是线程不安全的

remove

这里我们先看一下上面 listremove 操作

>>> import dis
>>> def test_remove():
...   a = [1]
...   a.remove(0)
... 
>>> dis.dis(test_remove)
 2      0 LOAD_CONST        1 (1)
       2 BUILD_LIST        1
       4 STORE_FAST        0 (a)

 3      6 LOAD_FAST        0 (a)
       8 LOAD_ATTR        0 (remove)
       10 LOAD_CONST        2 (0)
       12 CALL_FUNCTION      1
       14 POP_TOP
       16 LOAD_CONST        0 (None)
       18 RETURN_VALUE

从上面不难看出,整个 remove 操作被分成了好几条指令,这就意味着在多线程情况下会出现错乱的情况,试想一下,如果多线程下都去 remove 列表的话,并且不按照顺序,很容易出现问题。

append

在最上面我们说到,list append 操作是线程安全的,那么究竟是为什么呢?我们同样来用 dis 查看一下

8     19 LOAD_GLOBAL       0 (a)
      22 LOAD_ATTR        2 (append)
      25 LOAD_CONST        2 (1)
      28 CALL_FUNCTION      1
      31 POP_TOP

这里显然,append 也是有几条指令,势必在多线程执行的情况下也会发生交错,但是对于多线程下我们操作 append, 我们肯定也不会在乎这个时候 list 到顺序问题了,所以我们说它的 append 是线程安全的

参考

https://stackoverflow.com/questions/6319207/are-lists-thread-safe/19728536#19728536

https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe

以上就是详解Python多线程下的list的详细内容,更多关于Python多线程下的list的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python如何实现MySQL实例初始化详解
Nov 06 Python
Python第三方库face_recognition在windows上的安装过程
May 03 Python
Python实现的服务器示例小结【单进程、多进程、多线程、非阻塞式】
May 23 Python
利用python计算windows全盘文件md5值的脚本
Jul 27 Python
django 环境变量配置过程详解
Aug 06 Python
python向图片里添加文字
Nov 26 Python
numpy:np.newaxis 实现将行向量转换成列向量
Nov 30 Python
使用Python实现牛顿法求极值
Feb 10 Python
解决更改AUTH_USER_MODEL后出现的问题
May 14 Python
Python爬虫requests库多种用法实例
May 28 Python
numpy实现RNN原理实现
Mar 02 Python
python使用matplotlib绘制图片时x轴的刻度处理
Aug 30 Python
Python 字符串池化的前提
Jul 03 #Python
Pycharm打开已有项目配置python环境的方法
Jul 03 #Python
使用Dajngo 通过代码添加xadmin用户和权限(组)
Jul 03 #Python
windows支持哪个版本的python
Jul 03 #Python
Django Form设置文本框为readonly操作
Jul 03 #Python
完美解决TensorFlow和Keras大数据量内存溢出的问题
Jul 03 #Python
Keras 在fit_generator训练方式中加入图像random_crop操作
Jul 03 #Python
You might like
PHP中10个不常见却非常有用的函数
2010/03/21 PHP
PHP使用array_multisort对多个数组或多维数组进行排序
2014/12/16 PHP
PHP实现简单汉字验证码
2015/07/28 PHP
详解PHP安装mysql.so扩展的方法
2016/12/31 PHP
PHP基于新浪IP库获取IP详细地址的方法
2017/05/04 PHP
Yii2.0 RESTful API 基础配置教程详解
2018/12/26 PHP
Yii框架的布局文件实例分析
2019/09/04 PHP
laravel实现登录时监听事件,添加登录用户的记录方法
2019/09/30 PHP
基于jquery的划词搜索实现(备忘)
2010/09/14 Javascript
利用div+jquery自定义滚动条样式的2种方法
2013/07/18 Javascript
导入extjs、jquery 文件时$使用冲突问题解决方法
2014/01/14 Javascript
JQuery中操作Css样式的方法
2014/02/12 Javascript
js 获取input点选按钮的值的方法
2014/04/14 Javascript
JavaScript实现的圆形浮动标签云效果实例
2015/08/06 Javascript
JavaScript组件开发完整示例
2015/12/15 Javascript
JavaScript学习小结之使用canvas画“哆啦A梦”时钟
2016/07/24 Javascript
JS使用面向对象技术实现的tab选项卡效果示例
2017/02/28 Javascript
Node.js 路由的实现方法
2019/06/05 Javascript
javascript 代码是如何被压缩的示例代码
2020/05/06 Javascript
vue单应用在ios系统中实现微信分享功能操作
2020/09/07 Javascript
python中异常捕获方法详解
2017/03/03 Python
非递归的输出1-N的全排列实例(推荐)
2017/04/11 Python
关于Django显示时间你应该知道的一些问题
2017/12/25 Python
Python中__slots__属性介绍与基本使用方法
2018/09/05 Python
python 实现一次性在文件中写入多行的方法
2019/01/28 Python
详解Python locals()的陷阱
2019/03/26 Python
python 画二维、三维点之间的线段实现方法
2019/07/07 Python
学习Django知识点分享
2019/09/11 Python
python使用matplotlib绘制折线图的示例代码
2020/09/22 Python
html5+css如何实现中间大两头小的轮播效果
2018/12/06 HTML / CSS
瑞典灯具和照明网上商店:Lamp24.se
2018/03/17 全球购物
如何实现jdbc性能优化
2012/07/30 面试题
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
2012/11/24 面试题
文书工作总结(范文)
2019/07/11 职场文书
Go语言-为什么返回值为接口类型,却返回结构体
2021/04/24 Golang
HashMap实现保存两个key相同的数据
2021/06/30 Java/Android