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

by:授客 QQ:1033553122

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 的方式,绑定线程关联的东西,其它地方使用时,会自动匹配与线程关联的值

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

  1. 【学习笔记】Shell-1 变量:命名规范、变量赋值/取值/取消、局部变量/全局变量、预设环境变量

    1.Shell变量 从变量的实质上来说,变量名是指向一片用于存储数据的内存空间. Shell变量是一种弱类型的变量,即声明变量时不需要指定其变量类型,也不需求遵循“先声明再使用”的规定,想用即可用. ...

  2. TextBox只读时不能通过后台赋值取值解决办法

    给页面的TextBox设置ReadOnly="True"时,在后台代码中不能赋值取值,下边几种方法可以避免:  1.不设置ReadOnly,设置onfocus=this.blur( ...

  3. C# 基础控制台程序的创建,输出,输入,定义变量,变量赋值,值覆盖,值拼接,值打印

    基础学习内容有 Console.WriteLine("要输出的内容");//往外输出内容的 Console.ReadLine(); //等待用户输入,按回车键结束,防止程序闪退 控 ...

  4. Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值

    Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值 说到循环遍历,最常见的遍历数组/列表.Map等.但是,在开发过程中,有时需要循环遍历一个对象的所有属性.遍历对象的属性该如何遍历呢?查了 ...

  5. python练习题,写一个方法 传进去列表和预期的value 求出所有变量得取值可能性(例如list为[1,2,3,4,5,6,12,19],value为20,结果是19+1==20只有一种可能性),要求时间复杂度为O(n)

    题目:(来自光荣之路老师)a+b==valuea+b+c=valuea+b+c+d==valuea+b+c+d+...=valuea和b....取值范围都在0-value写一个方法 传进去列表和预期得 ...

  6. ASP.Net TextBox只读时不能通过后台赋值取值

    给页面的TextBox设置ReadOnly="True"时,在后台代码中不能赋值取值,下边几种方法可以避免: 1.不设置ReadOnly,设置onfocus=this.blur() ...

  7. switch条件变量的取值类型

    switch条件变量的取值类型主要有以下六种: 1)JDK1.5(不含JDK1.5)之前只能是byte.short.int.char类型,不能是float.double.long.boolean类型. ...

  8. C#多线程交替赋值取值

    static AutoResetEvent auto=new AutoResetEvent(false); ; ; static void Main() { Thread th1 = new Thre ...

  9. Loadrunner 关于参数赋值取值的操作

    1.参数的赋值和取值 lr_save_string("hello world","param"); lr_eval_string("{param}&q ...

随机推荐

  1. 使用线程统计信息(Thread Statistics)

    可在session log中使用线程统计信息来判断source,target或组的性能瓶颈 默认情况下,Integration Service在运行session时,使用一个reader thread ...

  2. websocket ----简介,以及demo

    #导报 from dwebsocket.decorators import accept_websocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户 ...

  3. Shell中判断文件,目录是否存在

    一. 具体每个选项对应的判断内容: -e filename 如果 filename存在,则为真 -d filename 如果 filename为目录,则为真 -f filename 如果 filena ...

  4. 微信小程序 获得用户输入内容

    在微信小程序里,如何获得用户输入的内容?? js: document.getElementById("Content").value jq:$("#Content&quo ...

  5. Django | 页面数据的缓存与使用

    为什么要使用缓存? 一个动态网站的基本权衡点就是,它是动态的. 每次用户请求页面,服务器会重新计算.从开销处理的角度来看,这比你读取一个现成的标准文件的代价要昂贵的多 使用缓存,将多用户访问时基本相同 ...

  6. List自带方法

    1.List的基础.常用方法:声明: 1.List<T> mList = new List<T>(); T为列表中元素类型,现在以string类型作为例子E.g.:List&l ...

  7. SpringBoot2.0应用(三):SpringBoot2.0整合RabbitMQ

    如何整合RabbitMQ 1.添加spring-boot-starter-amqp <dependency> <groupId>org.springframework.boot ...

  8. 【原创】Windows服务管家婆之Service Control Manager

    Service Control Manager,服务控制管理器,人称SCM就是它!在Windows内核中,都可以看到她忙碌的身影,可以说是系统服务和驱动的管家婆了!     SCM管家婆起早贪黑,每次 ...

  9. 计算n的阶乘有多少个尾随零

    思路一: 计算出n!= nValue,然后 nValue % 10 == 0 则nCount自增1,nValue /= 10 直到条件为否,最后nCount就是我们想要的结果,代码如下: int Co ...

  10. TensorFlow中的设备管理——Device的创建与注册机制

    背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 作为一款优秀的异构深度学习算法框架,TensorFlow可以在多种设备上运行算 ...