前言

listPython 常用的几个基本数据类型之一.正常情况下我们会对 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)

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

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

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

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

在最上面我们说到,listappend 操作是线程安全的,那么究竟是为什么呢?我们同样来用 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

多线程下的list的更多相关文章

  1. 多线程下NSOperation、NSBlockOperation、NSInvocationOperation、NSOperationQueue的使用

    本篇文章主要介绍下多线程下NSOperation.NSBlockOperation.NSInvocationOperation.NSOperationQueue的使用,列举几个简单的例子. 默认情况下 ...

  2. python 类变量 在多线程下的共享与释放问题

    最近被多线程给坑了下,没意识到类变量在多线程下是共享的,还有一个就是没意识到 内存释放问题,导致越累越大 1.python 类变量 在多线程情况 下的 是共享的 2.python 类变量 在多线程情况 ...

  3. Java多线程21:多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask

    CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就是CyclicBarrier.CyclicBarrier从字面理解是指循环屏障,它可以协同多个线程,让多个线程在这个屏障前等待,直到 ...

  4. Java多线程20:多线程下的其他组件之CountDownLatch、Semaphore、Exchanger

    前言 在多线程环境下,JDK给开发者提供了许多的组件供用户使用(主要在java.util.concurrent下),使得用户不需要再去关心在具体场景下要如何写出同时兼顾线程安全性与高效率的代码.之前讲 ...

  5. 多线程下C#如何保证线程安全?

    多线程编程相对于单线程会出现一个特有的问题,就是线程安全的问题.所谓的线程安全,就是如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是 ...

  6. 多线程下HashMap的死循环问题

    多线程下[HashMap]的问题: 1.多线程put操作后,get操作导致死循环.2.多线程put非NULL元素后,get操作得到NULL值.3.多线程put操作,导致元素丢失. 本次主要关注[Has ...

  7. ASP.NET多线程下使用HttpContext.Current为null解决方案 2015-01-22 15:23 349人阅读 评论(0) 收藏

    问题一:多线程下获取文件绝对路径 当我们使用HttpContext.Current.Server.MapPath(strPath)获取绝对路径时HttpContext.Current为null,解决办 ...

  8. ASP.NET多线程下使用HttpContext.Current为null解决方案 2015-01-22 15:23 350人阅读 评论(0) 收藏

    问题一:多线程下获取文件绝对路径 当我们使用HttpContext.Current.Server.MapPath(strPath)获取绝对路径时HttpContext.Current为null,解决办 ...

  9. ASP.NET多线程下使用HttpContext.Current

    本来要实现asp.net下使用tcp通讯方式向服务器获取数据,开始采用的方式是 参考: ASP.NET多线程下使用HttpContext.Current为null解决方案 http://www.cnb ...

  10. 多线程下的NSOperation和NSOperationQueue的使用

    多线程下的NSOperation和NSOperationQueue的使用 NSOperation和NSOperationQueue的介绍: NSOperation是Cocoa中的一个抽象类,用来封装单 ...

随机推荐

  1. java实现第三届蓝桥杯DNA对比

    DNA对比 脱氧核糖核酸即常说的DNA,是一类带有遗传信息的生物大分子.它由4种主要的脱氧核苷酸(dAMP.dGMP.dCMT和dTMP)通过磷酸二酯键连接而成.这4种核苷酸可以分别记为:A.G.C. ...

  2. 3、react-props/state

    1.react中属性props和状态state 属性--静态得,所以在初始化得时候使用得是static进行初始化得,正常情况下属性不改 状态--动态得,它得值是可以发生改变得,react中的组件更新( ...

  3. idea针对有外联jar包的项目如何编译成可运行的jar包

    1.打开file-->project structure 2.如下图所示,创建 3.在空白处右键点击“create directory”创建一个“”“libs”文件夹 4.把项目所需的jar吧, ...

  4. 关于GatewayClient 介绍和使用

    GatewayClient ## 源码 https://github.com/walkor/GatewayClient 根据GatewayWorker版本,选择合适的GatewayClient版本,请 ...

  5. kafka基本概念和hello world搭建

    什么是kafka? Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据 ...

  6. <Win10开发>一些小知识。

    这篇文章分享一下UWP开发的一些零散的小知识. 1.设置应用的最小尺寸 主要用在PC上,UWA在PC可以被鼠标随意摆弄,可大可小,界面的响应式设计是一大特点.不过有些时候还是要考虑,我们的App界面元 ...

  7. 青蛙的约会 (ax+by=c求最小整数解)【拓展欧几里得】

                                                  青蛙的约会(点击跳转) 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住 ...

  8. linux使用组ID(SGID)共享文件

    假如你有这样一个需求,一个小组内很多成员共同研究一个项目,为了这个项目我们需要分配一个具体的目录. 所有成员都拥有该目录的使用权限,可以互相操作成员的文件及内容.而且不允许其他人查看. 现在开始操作: ...

  9. 2019-02-13 思考:1000瓶药水,1瓶有毒,老鼠毒发24h,如何用最少的老鼠在24h内找出毒药?

    题目: 现在有1000瓶药水,其中一瓶有毒,一只老鼠喝了在24h后会准时死亡,药水无色无味,如何用最少的老鼠在24h内找出毒药? 分析: 时间限制为24h,说明我们只有一次喂老鼠的机会,需要一波找出来 ...

  10. c++的两个冒号::四个点是什么意思,什么作用呢?

    c++的两个冒号::四个点是什么意思,什么作用呢? 双冒号(::)用法 (1)表示“域操作符”例:声明了一个类A,类A里声明了一个成员函数void f(),但没有在类的声明里给出f的定义,那么在类外定 ...