前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python 列表是否线程安全?

Python 列表是否线程安全?

原创
作者头像
jackcode
发布于 2023-05-29 08:32:46
发布于 2023-05-29 08:32:46
44500
代码可运行
举报
文章被收录于专栏:爬虫资料爬虫资料
运行总次数:0
代码可运行
亿牛云代理
亿牛云代理

Python中的列表不是线程安全的,在多线程环境下,对列表的操作可能会导致数据冲突或错误。但是,并非所有列表操作都是线程不安全的。如果操作是原子的,也就是说不能被线程调度机制打断,那么就没有问题。比如L.append(x)和L.pop()就是原子操作,所以是thread安全。如果操作不是原子的,或者涉及修改多个列表元素,那么就需要使用锁或者其他同步机制来保证线程安全。例如,Li = Lj 和 L.append(L- 1) 不是原子操作,因此它们可能会导致冲突。可以使用 dis 模块来检查操作是否是原子操作。

例如下面就是多线程非安全操作:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
# 导入线程模块和dis模块
import threading
import dis

# 定义一个列表
L = [1, 2, 3, 4]

# 定义一个函数,用于对列表进行非原子操作
def swap(i, j):
    # 交换L[i]和L[j]的值
    L[i], L[j] = L[j], L[i]

# 定义一个函数,用于检查操作是否是原子操作
def check_atomic(func):
    # 使用dis模块的dis函数打印操作的字节码
    print(dis.dis(func))

# 创建两个线程,分别执行swap(0, 1)和swap(2, 3)
t1 = threading.Thread(target=swap, args=(0, 1))
t2 = threading.Thread(target=swap, args=(2, 3))

# 启动线程
t1.start()
t2.start()

# 等待线程结束
t1.join()
t2.join()

# 打印列表的结果
print(L)

# 检查swap函数是否是原子操作
check_atomic(swap)

输出结果可能是:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
[2, 1, 4, 3]
 10           0 LOAD_FAST                0 (i)
              2 LOAD_FAST                1 (j)
              4 ROT_TWO
              6 LOAD_GLOBAL              0 (L)
              8 STORE_SUBSCR

 11          10 LOAD_GLOBAL              0 (L)
             12 LOAD_FAST                1 (j)
             14 BINARY_SUBSCR
             16 LOAD_GLOBAL              0 (L)
             18 LOAD_FAST                0 (i)
             20 BINARY_SUBSCR
             22 ROT_TWO
             24 LOAD_GLOBAL              0 (L)
             26 STORE_SUBSCR
             28 LOAD_CONST               0 (None)
             30 RETURN_VALUE
None

可以看到,swap函数不是一个原子操作,因为它包含了多个字节码指令,而且涉及到对列表元素的修改。这样的操作在多线程环境下可能会导致数据冲突或错误。

下面是一个原子操作,因此是线程安全:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
# 导入线程模块、dis模块和requests模块
import threading
import dis
import requests

# 定义一个列表
L = []

# 定义一个函数,用于对列表进行原子操作
def append(x):
    # 向列表末尾添加元素x
    L.append(x)

# 定义一个函数,用于检查操作是否是原子操作
def check_atomic(func):
    # 使用dis模块的dis函数打印操作的字节码
    print(dis.dis(func))

# 定义一个函数,用于通过代理IP的用户名和密码方式进行网络传递
def send(proxy, username, password):
    # 设置代理IP的地址和端口
    proxy_url = f"http://{username}:{password}@{proxy}"
    # 设置代理IP的参数
    proxies = {
        "http": proxy_url,
        "https": proxy_url,
    }
    # 设置要传递的数据,这里假设是列表的长度
    data = {"length": len(L)}
    # 设置要传递的目标网址,这里假设是httpbin.org/post
    url = "http://httpbin.org/post"
    # 使用requests模块的post方法发送数据,并打印响应结果
    response = requests.post(url, data=data, proxies=proxies)
    print(response.text)

# 创建四个线程,分别执行append(1)、append(2)、append(3)和append(4)
t1 = threading.Thread(target=append, args=(1,))
t2 = threading.Thread(target=append, args=(2,))
t3 = threading.Thread(target=append, args=(3,))
t4 = threading.Thread(target=append, args=(4,))

# 启动线程
t1.start()
t2.start()
t3.start()
t4.start()

# 等待线程结束
t1.join()
t2.join()
t3.join()
t4.join()

# 打印列表的结果
print(L)

# 检查append函数是否是原子操作
check_atomic(append)

# 亿牛云(动态转发隧道代理) 爬虫代理加强版 设置代理信息
proxy = "www.16yun.cn:8080"
username = "16YUN"
password = "16IP"

# 通过代理IP的用户名和密码方式进行网络传递
send(proxy, username, password)

输出结果可能是:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
[1, 2, 3, 4]
 10           0 LOAD_GLOBAL              0 (L)
              2 LOAD_METHOD              1 (append)
              4 LOAD_FAST                0 (x)
              6 CALL_METHOD              1
              8 POP_TOP
             10 LOAD_CONST               0 (None)
             12 RETURN_VALUE
None

{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "length": "4"
  },
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Content-Length": "9",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.26.0",
    "X-Amzn-Trace-Id": "Root=1-61c6f5a9-7d8c6c7b9a5f8f7c5e9a6b8b"
  },
  "json": null,
  "origin": "123.456.789.10",
  "url": "http://httpbin.org/post"
}

可以看到,append函数是一个原子操作,因为它只包含了一个字节码指令,而且不涉及到对列表元素的修改。这样的操作在多线程环境下不会导致数据冲突或错误。另外通过代理IP的用户名和密码方式成功地将列表的长度传递给了目标网址,并得到了响应结果。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
线程安全的queue-浅谈线程安全那些事儿
  在并发编程时,如果多个线程访问同一资源,我们需要保证访问的时候不会产生冲突,数据修改不会发生错误,这就是我们常说的 线程安全 。
宜轩
2022/12/29
5240
Python后端面试(持续更新)
Python后端 Python后端技术栈 Web请求的流程 浏览器 负载均衡 Web框架 业务逻辑 数据库缓存 Python语言基础 语言特点 语法基础 高级特性 算法与数据结构 常用算法和数据结构 分析时间、控件复杂度 实现常见数据结构和算法 编程范式 面向对象编程 常用设计模式 函数式编程 操作系统 常用Linux命令 进程、线程 内存管理 网络编程 常用协议TCP、IP、HTTP Socket编程基础 Python并发库 数据库 Mysql常考,索引优化 关系型和NoSQL的使用场景 Redis缓存
dreamkong
2019/03/19
2K0
Python后端面试(持续更新)
【PY】Python3 字节码详解
在逆向的时候遇到过反编译 py 字节码,之前也就没咋在意,啥不会查就完事儿了,好家伙,省赛让我给遇到了,直接嘤嘤嘤😭,但还好解出来了;
sidiot
2023/08/31
3550
【PY】Python3 字节码详解
python中urllib的使用
urllib库是Python中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。
小白学大数据
2023/05/25
3180
python—多线程
  线程时应用程序中工作的最小单位,python中提供了threading模块来对多线程操作,一般多核cpu采用多进程方式,单核才采用多线程方式
py3study
2020/01/06
5760
“五一”出游你回来的机票还有吗?
今年”五一“已经是可以预见的火爆了,特别是关了三年的大学生们成为了穿梭城市的“特种兵”。短视频平台上的都是各种极限24小时打卡旅游地,景区充斥着各种中老年团,各个地区旅游局的局长为了宣传各种卷。
小白学大数据
2023/04/21
3370
py基础---多线程、多进程、协程
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程中并发执行不同的任务。
py3study
2020/01/16
6750
py基础---多线程、多进程、协程
使用多线程或异步技术提高图片抓取效率
图片抓取是爬虫技术中常见的需求,但是图片抓取的效率受到很多因素的影响,比如网速、网站反爬机制、图片数量和大小等。本文将介绍如何使用多线程或异步技术来提高图片抓取的效率,以及如何使用爬虫代理IP来避免被网站封禁。
jackcode
2023/09/07
3790
使用多线程或异步技术提高图片抓取效率
汽车行业也开始搞降价大促销活动了
最近两天,关于湖北购车最高补贴9万元超级大促销席卷朋友圈和社交平台,很多的消费者参加了这个大促销活动,很多4S店表示目前已经无法接单,连展车都卖掉了。
小白学大数据
2023/03/09
5.6K0
python之线程、进程
    从列表中取一个数据,相当于是复制了一份列表中的数据,列表中的元数据并没有被改动
py3study
2020/01/03
3790
python爬取叮咚买菜评价数据
疫情这这几年,线上买菜成了大家日常生活的一部分,出现了叮咚买菜,京东到家,朴朴超市等app,这些买菜app我们可以买到新鲜蔬菜、水果、肉禽蛋、米面粮油、水产海鲜、南北干货、方便速食等等。对上班族来说真的是很方便的软件。
小白学大数据
2023/05/22
4950
如何破解一个Python虚拟机壳并拿走12300元ETH
之前在群里看到有人发了一个挑战,号称将 5 ETH 的私钥放在了加密的代码中,只要有人能解密就可以取走,所以我又管不住自己这双手了。
evilpan
2023/02/12
5800
如何破解一个Python虚拟机壳并拿走12300元ETH
python线程、协程
如果同一时间有多个线程操作同一数据可能会出现混乱现象,所以需要加线程锁保证同一时间只有一个线程操作这一数据,保证数据一致性
py3study
2020/01/13
3110
Python 多线程操作
线程(Thread)也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。 举个简单的例子来理解下: 假定有一 7 * 24 小时不停工的工厂,由于其电力有限,一次仅供一个车间使用,当一个车间在生产时,其他车间停工。在这里我们可以理解这个工厂相当于操作系统,供电设备相当于 CPU,一个车间相当于一个进程。
somenzz
2020/12/10
8970
Python 多线程操作
日常代码笔记,python的推导式&性能评估
写代码跟写作类似,需要不断地练习,不断地阅读,获得灵感,然后反复修改(重构)。写代码有代码补全工具,然后我们还是需要不断地练习、实验自己的新想法。
mixlab
2019/09/23
6100
日常代码笔记,python的推导式&性能评估
python线程及多线程(果断收藏)
之前做了一个有关数据处理的项目,一个源文件大概20G(超大文件),我的计算机内存只有8G,在第一步读取文件时内存直接就爆了,后来总结了俩种方法:
用户5745385
2019/07/04
1.2K0
python线程及多线程(果断收藏)
Python 的多线程与 GIL
Python从0.9.8版就开始支持多线程( thread模块),1.5.1版引入了 threading高级模块,是对thread模块的封装。
CS实验室
2021/03/22
1K0
Python 的多线程与 GIL
你领到国家的退税“红包”了吗?
很多网友在3月1日凌晨申请退税,纷纷晒出自己的退税金额,有的人退税金额超过万元,直呼:真香!
小白学大数据
2023/03/01
3200
你了解 Python 字节码的原理吗?
如果你曾经写过或者用过 Python,你可能已经习惯了看到 Python 源代码文件;它们的名称以.Py 结尾。你可能还见过另一种类型的文件是 .pyc 结尾的,它们就是 Python “字节码”文件。这里转载一篇文章,专门讲解 Python 字节码的相关内容,给大家看看。
崔庆才
2019/06/14
2.7K0
你了解 Python 字节码的原理吗?
python线程间通信的方式_android 线程间通信
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/188613.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/27
7250
相关推荐
线程安全的queue-浅谈线程安全那些事儿
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验