专栏首页授客的专栏Python_关于多线程下变量赋值取值的一点研究

Python_关于多线程下变量赋值取值的一点研究

1.代码实践1

#!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'shouke' #!/usr/bin/env python # -*- coding:utf-8 -*- import threading import time class TestClass: def __init__(self, num): self.num = num global_var = 0 def testfn(num, obj): global global_var global_var = num local_var = num * 2 obj.num = num * 2 time.sleep(5) print("thread id:", threading.get_ident(), 'num:', num, 'obj.num:', obj.num, 'local_var:', local_var, 'global_var:', global_var) for i in range(0, 5): # # 多线程执行性能监控 thread = threading.Thread(target=testfn, name="testfn"+str(i), args=(i, TestClass(i))) thread.start()

结论:

1、如下,通过args给线程即将调用函数(为方便描述,暂且称它为 “线程函数”)传递参数,可以做到每个线程都使用各自的参数去调用线程函数。

thread = threading.Thread(target=testfn, name="testfn"+str(i), args=(i, TestClass(i)))

2、如下,线程函数里的局部变量(例中除去global_var之外的变量),都存储在栈内存中,而每个线程都有自己的栈内存,彼此独立,所以,每个线程对局部变量的赋值,读取操作互不影响。也就是说,多线程并发的情况下,局部变量是“安全”的,而全局变量存储在堆内存中,堆内存为所有线程共享,对所有线程都是可见的,所以两个以上的线程访问全局变量时,就会出现所谓的“不安全”,如下,第一个线程访问了全局变量 global_var,赋值为对应的num,然后中间sleep了5秒,在此期间,另一个线程访问了全局变量,赋值为另一个num,然后第一个线程醒来了,发现全局变量 global_var 已经不是它要的值了。

def testfn(num, obj): global global_var global_var = num local_var = num * 2 obj.num = num * 2 time.sleep(5)

2.代码实践2

#!/usr/bin/env python # -*- coding:utf-8 -*- import threading import time thread_local_obj = threading.local() class TestClass: def __init__(self, num): self.num = num global_var = 0 def testfn(num, obj): global global_var global_var = num local_var = num * 2 obj.num = num * 2 thread_local_obj.obj = obj time.sleep(5) other_task() print("thread id:", threading.get_ident(), 'num:', num, 'obj.num:', obj.num, 'local_var:', local_var, 'global_var:', global_var) def other_task(): print("thread id:", threading.get_ident(), 'obj.num:', thread_local_obj.obj.num , threading.currentThread().name) for i in range(0, 5): # # 多线程执行性能监控 thread = threading.Thread(target=testfn, name="testfn"+str(i), args=(i, TestClass(i))) thread.start()

如上,线程函数中调用了另一个函数,我们希望在这个函数中做些操作,比如读取和线程关联的对象的属性值、修改属性值,这个按常规思维也可以通过传递函数参数来实现, 如下

other_task(obj):

print(obj.num)

问题是,线程函数里可能会调用多个函数,被调用的每个函数也可能会调用多个函数,所有这些函数都可能用到线程关联的对像,这样的话,需要逐层传递参数,很麻烦

解决方案:

创建全局对象,如下

thread_local_obj = threading.local()

然后在 线程函数 里通过 thread_local_obj.attr = xxx 的方式,绑定线程关联的东西,其它地方使用时,会自动匹配与线程关联的值

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MariaDB MySQL变量取值避免四舍五入的方法

    在一些对数据精确度要求比较高的场景(比如资金结算)下,变量取值时不能对变量值进行四舍五入操作,这时候就要做些预处理工作。

    授客
  • Python @classmethod和@staticmethod装饰器使用介绍

    静态方法:类中用 @staticmethod装饰的不带 self 参数的方法。类的静态方法可以直接使用类名调用。

    授客
  • JQuery 获取元素到浏览器可视窗口边缘的距离

    https://gitee.com/ishouke/front_end_plugin/blob/master/jquery-3.2.1.min.js

    授客
  • Exchange 2003 升级 2010地址列表升级

    在Exchange 2003的时代,地址列表都是基于LDAP语句的,Exchange 2007之后,地址列表语法开始采用了OPATH语法进行查询。所以,当我们把...

    李珣
  • Redis学习系列七分布式锁

    熟悉.Net多线程的都知道,当多个线程同时操作一个全局缓存对象(static对象实例、Dictionary、List等)时,会存在多线程争用问题,包括EF、Da...

    郑小超.
  • RxJava 详解

    我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ...

    AWeiLoveAndroid
  • 逐梦启航,2019年度犀牛鸟精英人才入选者开启研究新征程

    ? 随着产业互联网的发展进入“快车道”,基础研究作为产业互联网的核心推动力,培养更多优秀的科技领军人才也变得尤为重要。为了更好协同产学研各方资源,加速研究型...

    腾讯高校合作
  • 产品经理从0到1要避免哪些坑?

    - 成都- 如果你在做互联网,那么应该会有这个疑问:为什么雷军、马化腾、张小龙等都在强调自己是产品经理?“如果你只是自己厨艺好,那最多是个好厨子,但是做不了好...

    腾讯大讲堂
  • ActiveReports 报表应用教程 (4)---分栏报表

    在葡萄城ActiveReports报表中可以实现分栏报表布局样式,可以设置横向分栏、纵向分栏,同时进行分栏和分组设置,统计分栏分组的小计、合计等。在商业报表系统...

    葡萄城控件
  • mysql修改表、字段、库的字符集

    来源:http://www.diannaowa.com/index.php/archives/233

    东营浪人

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动