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

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. deepin卸载mysql并安装设置mysql5.7

    mysql完全卸载以及安全安装 完全卸载 sudo apt purge mysql-* sudo rm -rf /etc/mysql/ /var/lib/mysql sudo apt autoremo ...

  2. (转)asyncio --- 异步 I/O

    原文:https://docs.python.org/zh-cn/3/library/asyncio.html asyncio 是用来编写 并发 代码的库,使用 async/await 语法. asy ...

  3. Centos6.5搭建grok匹配测试网站

    最近在使用ELK对日志进行集中管理,因为涉及到日志的规则经常要用到http://grokdebug.herokuapp.com/进行调试,但是国外的网站访问太慢,这儿推荐一个国内的网站http://g ...

  4. Linux编程 24 shell编程(结构化 if [ condition ] 数值比较,字符串比较)

    一.概述 接着上篇讲的结构化命令,最后讲到了test命令的另一种写法 if [ condition ],它的语法格式如下: --格式如下: if [ condition ] then commands ...

  5. Android--UI之ScrollView

    前言 本篇博客主要讲解ScrollView和HorizontalScrollView两个容器的使用.它们分别代表了垂直滚动以及水平滚动,滚动的内容是它其中包含的View.在本篇会简单介绍ScrollV ...

  6. 1197多行事务要求更大的max_binlog_cache_size处理与优化

    1197多语句事务要求更大的max_binlog_cache_size报错   binlog_cache_size:为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存,提高记录bi ...

  7. Leetcode 1-10

    这篇文章介绍Leetcode1到10题的解决思路和相关代码. 1. Two sum 问题描述:给定一个整数数组,返回两个数字的索引,使它们加起来等于一个特定的目标. 例子: Given nums = ...

  8. SpringMVC学习(二)———— 参数绑定

    一.参数绑定 1.1.什么是参数绑定? 客户在浏览器端会提交一些参数到服务器端,比如用户的登录等,就会传username 和 password过来,springmvc则通过参数绑定组件将请求参数的内容 ...

  9. Perl数据序列化和持久化(入门):Storable模块

    Perl提供了一个Storable模块,用来对数据结构进行序列化(serialization,Perl中称为冻结),也就是将数据结构保存为二进制数据. 序列化后的数据可以写入文件实现持久化,可以将持久 ...

  10. 入侵感知系列之webshell检测思路

    Webshell检测   背景: 在B/S架构为主流的当下,web安全成了攻防领域的主战场,其中上传webshell是所有web黑客入侵后一定会做的事,所以检测网站中是否有webshell程序是判断被 ...