Python — 线程安全问题

Python — 线程安全问题前言当多个线程同时修改同一数据时 会导致最终的数据出现的不是正确的值所以出现了线程锁 即同一时刻只允许一个线程执行操作 这样可以确保数据的准确性示例代码 Time 2021 6 169 15importthre 0 多个线程操作的全局变量 tname lambda threading currentThrea name 获取当前线程名称 deftask print f 线程开始


前言

  • 当多个线程操作同一数据时,会导致该数据出现的不是正确的值
  • 所以出现了线程锁,即同一时刻只允许一个线程执行操作,这样可以确保数据的准确性



示例代码

# -*- coding: utf-8 -*- # @Author : zbz import threading import time num = 0 # 多个线程操作的全局变量 tname = lambda: threading.currentThread().name # 获取当前线程名称 def task(): print(f"线程开始... ({       tname()})") global num for j in range(10_0000): num += 1 print(f"线程结束... ({       tname()})") def main(): t1 = time.time() ts = [] for j in range(10): t = threading.Thread(target=task) ts.append(t) for t in ts: t.start() for t in ts: t.join() print(f"num: {       num}") print(f"耗时: {       time.time() - t1}") if __name__ == '__main__': main() 
  • 上方代码中,总共有10个线程全局变量num进行操作,每个线程都是把num的值增加10w
  • 所以当所有线程结束后,num正确的值应为 10 × 10w = 100w



代码运行

在这里插入图片描述

  • 结果并不是100w
  • 因为线程并没有上锁
  • 运行结束总共耗时0.1s,记住这个时间,后面会说到

上锁

# @Time : 2021/6/16 9:26 import threading import time num = 0 lock = threading.Lock() # 线程锁 tname = lambda: threading.currentThread().name def task(): print(f"线程开始... ({ 
       tname()})") global num for j in range(10_0000): lock.acquire() # 获取锁 num += 1 lock.release() # 释放锁 print(f"线程结束... ({ 
       tname()})") def main(): t1 = time.time() ts = [] for j in range(10): t = threading.Thread(target=task) ts.append(t) for t in ts: t.start() for t in ts: t.join() print(f"num: { 
       num}") print(f"耗时: { 
       time.time() - t1}") if __name__ == '__main__': main() 
  • 不难看出,只是在操作num的上下加了获取锁释放锁这两句代码
  • 因为之前就是在同一时刻,有多个线程操作num的值,所以最后num的值才会不准确

代码运行

在这里插入图片描述

  • 可以看到最后num的值准确的100w
  • 运行结束总共耗时3s,因为上锁的时候,同一时刻只能有一个线程执行,所以其他线程在等待锁的释放,这里消耗了时间,所以时间比之前的不上锁(耗时0.1s)耗费的时间长




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224696.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午11:21
下一篇 2026年3月17日 上午11:21


相关推荐

  • ubuntu 安装redis

    ubuntu 安装redis1 下载 redis 安装包在 window 环境访问地址 http redis io download 本例版本为 redis 6 0 9 tar gz2 将安装包传服务器上通过 ftp 方式传输安装包到目录 opt 下 路径可修改 本例为 opt3 解压安装包 并将解压后的文件移动到 etc 目录下解压 redis 安装包 执行 tar xzfredis 6 0 9 tar gz 将解压后的文件 移动到 etc 目录下 mvredis 6 0 9 etc

    2026年3月19日
    2
  • Java中将Map转String,String转Map

    Java中将Map转String,String转Map暴力的直接 Map 对象 toString 存 后面取出是就是用再转换为 MapString 转 Map JSONObjectjs JSONObject fromObject str rMap Map String Object jsonobject 但很多时候并不能直接将 Map 对象的 toString 而是应该转换为 JsonObject 后再调用 toString 后存入就正常了 Map String Object map newHashMa String Object String Object

    2026年3月19日
    3
  • 邻接表&十字链表

    邻接表&十字链表邻接表:每一行都可以看成一个单链表,第一行中,v0-1-3可以得到,v0的出度为v1和v3。邻接表完整代码:#include<iostream>usingnamespacestd;constintMAX_V=15;//边节点typedefstructEdge_node{chardata;Edge_node*next;}E…

    2022年6月18日
    34
  • 什么是cs什么是bs_bs代替CS

    什么是cs什么是bs_bs代替CSC/S结构,即Client/Server(客户机/服务器)结构,是大家熟知的软件系统体系结构,通过将任务合理分配到Client端和Server端,降低了系统的通讯开销,可以充分利用两端硬件环境的优势。早期的软件系统多以此作为首选设计标准。。 B/S结构,即Browser/Server(浏览器/服务器)结构,是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。在这种结构下

    2025年10月13日
    3
  • java过滤器和拦截器的区别_spring拦截器和过滤器

    java过滤器和拦截器的区别_spring拦截器和过滤器集成拦截器登录验证为例添加拦截器public class LoginInterceptor implements HandlerInterceptor { private Logger log = LoggerFactory.getLogger(getClass()); //Controller逻辑执行之前 @Override public boolean preHandle(HttpServletRequest request, HttpServletRe

    2022年8月9日
    10
  • OpenClaw生态比你想象的要大:15个插件和技能排名

    OpenClaw生态比你想象的要大:15个插件和技能排名

    2026年3月13日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号