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

 

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

 

by:授客 QQ1033553122

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()

 

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

 

 

 

结论:

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

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

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

 


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

 


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

other_task(obj):

print(obj.num)

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

 

解决方案:

创建全局对象,如下

thread_local_obj = threading.local()

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

 

 

posted @ 2018-06-20 22:49  授客  阅读(5294)  评论(0编辑  收藏  举报