Python多任务编程——线程之间共享变量

简介: 线程之间共享全局变量数据出错

问题:线程之间共享全局变量数据出错


importthreadingg_num=0deftask1():
foriinrange (1000000):
globalg_numg_num+=1print('TASK1:',g_num)
deftask2():
foriinrange (1000000):
globalg_numg_num+=1print('TASK2:',g_num)
if__name__=="__main__":
first=threading.Thread(target=task1)
second=threading.Thread(target=task2)
first.start()
second.start()

运行结果:

e884949cb94ee45ed85b86a86ed0eea9.png


理论上实现循环100万次,每循环一次给全局变量加1,最终的结果应该为2000000。实际上的结果为上图所示。


原因:


 两个线程同时对全局变量进行了操作,当线程1读取了全局变量的同时,线程2也读取了全局变量。在进行对变量操作的时候,读取的是原来的变量,并不是操作后的变量。因为线程1对变量操作后未提交,线程2读取的也是前一个变量值。

解决方法


使用进程同步,确保在同一时间内只有一个线程对数据进行操作。


1.使用join()方法


importthreadingg_num=0deftask1():
foriinrange (1000000):
globalg_numg_num+=1print('TASK1:',g_num)
deftask2():
foriinrange (1000000):
globalg_numg_num+=1print('TASK2:',g_num)
if__name__=="__main__":
first=threading.Thread(target=task1)
second=threading.Thread(target=task2)
first.start()
first.join()
second.start()

执行结果:


65ccb29683aa1e0042ae999bfbd0c5aa.png


原理:添加了first.join()线程等待在程序运行时,当first线程运行完成后才会开始运行second线程,确保了在同一时刻只有一个线程对变量进行操作。

线程同步: 一个任务执行完成以后另外一个任务才能执行,同一个时刻只有一个任务在执行。


2.互斥锁


importthreadingg_num=0#创建互斥锁 本质上是一个函数 通过LOCK=threading.Lock()
deftask1():
# 上锁LOCK.acquire()
foriinrange (1000000):
globalg_numg_num+=1print('TASK1:',g_num)
# 释放锁LOCK.release()
deftask2():
LOCK.acquire()
foriinrange (1000000):
globalg_numg_num+=1print('TASK2:',g_num)
LOCK.release()
if__name__=="__main__":
first=threading.Thread(target=task1)
second=threading.Thread(target=task2)
first.start()
second.start()


执行结果:


65ccb29683aa1e0042ae999bfbd0c5aa.png


原理:对共享数据锁定,同一时间只有一个线程去操作 ,多个线程一起去抢,抢到的先执行使用了threading中的lock函数。在运行first线程时,先用lock.acquire()把当前线程锁起来,在此期间其他线程无法运行,当循环结束后使用lock.release()把当前线程线程释放,此后其他线程可以进行操作。确保在同一时刻只能进行同一个线程。

但是互斥锁在一定程度上影响了代码的效率,把多任务变成了单任务执行,同时也有可能带来死锁的问题(锁没有及时的释放导致)。

目录
相关文章
|
30天前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
12天前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
24天前
|
Java Unix 调度
python多线程!
本文介绍了线程的基本概念、多线程技术、线程的创建与管理、线程间的通信与同步机制,以及线程池和队列模块的使用。文章详细讲解了如何使用 `_thread` 和 `threading` 模块创建和管理线程,介绍了线程锁 `Lock` 的作用和使用方法,解决了多线程环境下的数据共享问题。此外,还介绍了 `Timer` 定时器和 `ThreadPoolExecutor` 线程池的使用,最后通过一个具体的案例展示了如何使用多线程爬取电影票房数据。文章还对比了进程和线程的优缺点,并讨论了计算密集型和IO密集型任务的适用场景。
46 4
|
24天前
|
人工智能 Python
[oeasy]python039_for循环_循环遍历_循环变量
本文回顾了上一次的内容,介绍了小写和大写字母的序号范围,并通过 `range` 函数生成了 `for` 循环。重点讲解了 `range(start, stop)` 的使用方法,解释了为什么不会输出 `stop` 值,并通过示例展示了如何遍历小写和大写字母的序号。最后总结了 `range` 函数的结构和 `for` 循环的使用技巧。
31 4
|
6天前
|
数据采集 Java Python
爬取小说资源的Python实践:从单线程到多线程的效率飞跃
本文介绍了一种使用Python从笔趣阁网站爬取小说内容的方法,并通过引入多线程技术大幅提高了下载效率。文章首先概述了环境准备,包括所需安装的库,然后详细描述了爬虫程序的设计与实现过程,包括发送HTTP请求、解析HTML文档、提取章节链接及多线程下载等步骤。最后,强调了性能优化的重要性,并提醒读者遵守相关法律法规。
35 0
|
1月前
|
Python
Python中的多线程与多进程
本文将探讨Python中多线程和多进程的基本概念、使用场景以及实现方式。通过对比分析,我们将了解何时使用多线程或多进程更为合适,并提供一些实用的代码示例来帮助读者更好地理解这两种并发编程技术。
|
1月前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
66 0
|
1月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
48 1
C++ 多线程之初识多线程
|
29天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3
下一篇
无影云桌面