python进阶之多线程对同一个全局变量的处理方法

作者:Jonny0318 时间:2023-09-29 19:03:58 

通常情况下:


from threading import Thread

global_num = 0

def func1():
global global_num
for i in range(1000000):
global_num += 1
print('---------func1:global_num=%s--------'%global_num)

def func2():
global global_num
for i in range(1000000):
global_num += 1
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)

lock = Lock()

t1 = Thread(target=func1)
t1.start()

t2 = Thread(target=func2)
t2.start()

输出结果:


global_num=0
---------func1:global_num=1492752--------
--------fun2:global_num=1515462

#由于多线程不像多进程一样,每一个进程都一个独立的资源块,线程之间是共享主线程的一个资源块(虽然这样说不合适)

#这样虽然方便了线程之间的数据传递,但是又会由于线程之间执行顺序的不确定,导致最后的结果不是应该输出的正确结果。

#例如下面的例程,如果没有添加global_flag标志全局变量,就会出现,虽然逻辑上最后的结果是2000000(之所以选择这么大的一个数,是因为可以更明显的看出#这个问题),

#但是实际上并不是这个结果,而是一个小于2000000的结果,但是不排出偶然会出现2000000,这是一个极为理想的结果,这是为什么呢?

#主要还是由于线程被cpu调用的顺序不确定。具体来讲就是当主线程创建出两个子线程,分别是t1和t2,他们有分别指向func1()和func2()。

#在这两个线程中的函数中,都有一句“global_num += 1”,在计算机内部cpu执行时,这一条语句实际上是两个过程:第一个过程是从内存中读取global_num的值,完成加一操作,这个时候global_num的值还是原来的值;第二个过程是将求和的值付给global_num,这时候global_num的值才会更新。在程序执行过程中会出现这种

#情况:当cpu在执行线程t1中的语句到求和那条语句时,在执行完第一个过程停了下来,将线程t1抛出,转而执行线程t2,当线程执行一段时间后也出现这中情况

#有转而执行线程t1,这时,正好执行求和语句的第二个过程,完成最初的赋值,那么这一段时间内的整个求和就等于没做,所以出现这中最后结果不是2000000的##情况

#解决这种情况可以利用添加一个变量,利用“轮询”的方式执行,但是这样做的效率很低,而且还浪费cpu,所以一般采用“通知”方式来做。

轮询方式:


from threading import Thread

global_num = 0
global_flag = 0

def func1():
global global_num
global global_flag
if global_flag == 0:
for i in range(1000000):
global_num += 1
global_flag = 1
print('---------func1:global_num=%s--------'%global_num)

def func2():
global global_num
while True:
if global_flag != 0:
for i in range(1000000):
global_num += 1
break
print('--------fun2:global_num=%s'%global_num)

print('global_num=%s'%global_num)

t1 = Thread(target=func1)
t1.start()

t2 = Thread(target=func2)
t2.start()

运行结果:


global_num=0
---------func1:global_num=1000000--------
--------fun2:global_num=2000000

通知方式:


from threading import Thread,Lock

global_num = 0

def func1():
global global_num
for i in range(1000000):
lock.acquire()#两个线程会最开始抢这个锁,拿到锁就会处于关锁,执行后面的程序,其他线程执行处于监听状态,等待这个线程开锁,再抢锁
global_num += 1
lock.release()
print('---------func1:global_num=%s--------'%global_num)

def func2():
global global_num
for i in range(1000000):
lock.acquire()
global_num += 1
lock.release()
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)

lock = Lock()

t1 = Thread(target=func1)
t1.start()

t2 = Thread(target=func2)
t2.start()

输出结果:


global_num=0
---------func1:global_num=1901175--------
--------fun2:global_num=2000000

来源:https://blog.csdn.net/m0_37338590/article/details/78481671

标签:python,多线程,全局变量
0
投稿

猜你喜欢

  • 使用sublime text3搭建Python编辑环境的实现

    2023-01-20 21:01:56
  • 使用javaScript动态加载Js文件和Css文件

    2024-04-19 10:16:27
  • Python机器学习之决策树算法实例详解

    2022-10-06 07:24:37
  • Python之time模块的时间戳,时间字符串格式化与转换方法(13位时间戳)

    2023-07-25 08:46:01
  • python里读写excel等数据文件的6种常用方式(小结)

    2021-04-09 08:11:52
  • php抓取页面的几种方法详解

    2023-11-14 10:53:42
  • 分析mysql中一条SQL查询语句是如何执行的

    2024-01-19 15:43:59
  • ASP URL反编码函数代码

    2011-02-28 11:04:00
  • MySQL函数与存储过程字符串长度限制的解决

    2024-01-16 13:17:01
  • javascript延时重复执行函数 lLoopRun.js

    2024-04-22 13:22:57
  • python 爬取天气网卫星图片

    2022-01-11 15:52:48
  • TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南

    2023-07-30 10:28:08
  • python实现将中文日期转换为数字日期

    2023-07-10 10:39:33
  • Django项目后台不挂断运行的方法

    2021-09-28 05:04:54
  • MySQL里Create Index 能否创建主键 Primary Key

    2024-01-21 07:12:49
  • Python创建系统目录的方法

    2023-11-22 11:52:47
  • anaconda jupyter不能导入安装的lightgbm解决方案

    2021-09-15 19:24:45
  • uniapp使用百度地图的保姆式教学(适合初学者!)

    2024-04-29 14:06:21
  • ASP同一站点不同编码程序出现乱码解决办法

    2008-11-10 12:08:00
  • pytorch绘制曲线的方法

    2022-09-03 06:43:54
  • asp之家 网络编程 m.aspxhome.com