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

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. mysql 开发基础系列4 字符数据类型

    字符串类型 1.1 CHAR 和VARCHAR 类型 CHAR 列的长度固定为创建表时声明的长度,VARCHAR 列中的值为可变长字符串.在检索的时候,CHAR 列删除了尾部的空格,而VARCHAR ...

  2. C#--对象转Json序列化

    前言 最近在研究Android项目,其中涉及到Android中解析Json数据的问题,需要模拟网络中传递Json数据的模式,因为以前是.net的工程师,所以想着从.net的平台开发服务,传递Json格 ...

  3. JVM源码分析之SystemGC完全解读

    JVM源码分析之SystemGC完全解读 概述 JVM的GC一般情况下是JVM本身根据一定的条件触发的,不过我们还是可以做一些人为的触发,比如通过jvmti做强制GC,通过System.gc触发,还可 ...

  4. poj1001

    #include <iostream> #include<iomanip> #include<cstring> using namespace std; int s ...

  5. ACM--string常见用法

    在ACM竞赛中,常常需要将读入的数字的每位分离出来,如果采用取余的方法,花费的时间就会太长,这时候,我们可以将读入的数据当成字符串来处理,这样就方便.省时多了.下面这个程序演示了求一个整数各位的和: ...

  6. springboot情操陶冶-SpringApplication(二)

    承接前文springboot情操陶冶-SpringApplication(一),本文将对run()方法作下详细的解析 SpringApplication#run() main函数经常调用的run()方 ...

  7. 使用3D Slicer进行颅骨去除

    关于3D Slicer的下载.安装及模块安装在上一篇博客中以及介绍过,以下将专注于使用3D Slicer进行颅骨去除 准备 此次,我们需要安装SwissSkullStripper模块,安装后需要重启软 ...

  8. Linux常用性能工具功能、用法及原理(一)

    Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息. 按实现原理分,可分为基于计数器和跟踪以及剖析.含义如下: 计数器 ...

  9. 使用meterpreter让没有安装python解释器的肉鸡设备执行任意python程序

    目标设备不需安装python解释器就能让其执行python程序 # 需要在与目标meterpreter的session中加载python模块 meterpreter > load python ...

  10. LeetCode链表解题模板

    一.通用方法以及题目分类 0.遍历链表 方法代码如下,head可以为空: ListNode* p = head; while(p!=NULL) p = p->next; 可以在这个代码上进行修改 ...