1. Python Threading介绍
Python中的Threading模块可以让开发者创建多线程,提高程序效率。线程是操作系统中进行调度的最小单位,比进程更轻量级。
2. Local()函数介绍
我们都知道,多线程中访问全局变量是线程不安全的,而解决方案之一便是使用线程局部变量Thread Local Storage。Python threading模块的Local()函数就是用来创建线程局部变量。
2.1 Local()函数的定义
class threading.local()
Local()函数返回一个Threadlocal类型的实例,它是用来存储线程局部变量的。我们将这个实例称为“local变量”,具体实现中它是一个字典。
2.2 Local()函数的用法
Local()函数的用法非常简单,只需要在需要使用线程局部变量的地方进行如下操作:
local_var = threading.local()
这样我们就创建了一个线程局部变量local_var。
2.3 属性和方法
Threadlocal类型的实例拥有以下属性和方法:
local_var.attr1 = value1:设置变量
local_var.attr1:获取变量
local_var.__dict__:获取所有变量
local_var.__class__:返回Threadlocal类
local_var.__del__():删除当前线程关联的所有变量
3. Local()函数实例
下面我们来看一个例子,通过Local()函数创建一个线程局部变量temperature:
import threading
# 创建线程局部变量
local_var = threading.local()
def print_temperature():
print('temperature = %f' % local_var.temperature)
def set_temperature(temp):
local_var.temperature = temp
print_temperature()
if __name__ == '__main__':
set_temperature(0.5)
print_temperature()
如果直接运行程序,输出如下:
temperature = 0.500000
AttributeError: '_thread._local' object has no attribute 'temperature'
在这个例子中,我们创建了一个线程局部变量temperature,并通过set_temperature()函数来设置这个温度。
但是,运行结果并不是我们期望的那样,错误提示:'_thread._local' object has no attribute 'temperature'。这是为什么呢?
3.1 原因分析
在上面的代码中,我们创建了局部变量local_var,但它是在主线程中创建的,而不是在其他子线程中。因此,在子线程中是找不到这个局部变量的。
3.2 解决方案
解决这个问题很简单,我们只需要在实际的线程中创建这个局部变量即可:
import threading
local_var = threading.local() # 在主线程中创建局部变量
def print_temperature():
print('temperature = %f' % local_var.temperature)
def set_temperature(temp):
local_var.temperature = temp
print_temperature()
if __name__ == '__main__':
t = threading.Thread(target=set_temperature, args=(0.5,))
t.start()
t.join()
print_temperature()
这个程序中我们再次创建了局部变量local_var,然后在线程中设置temperature并进行输出。输出结果如下:
temperature = 0.500000
temperature = 0.000000
这个输出结果仍然不符合我们的预期。原因是,我们在主线程中创建的局部变量local_var并没有和其他线程关联起来,因此其他线程无法访问它。
此时我们需要重新定义set_temperature()函数,让它在每一个线程中都创建并设置temperature。
def set_temperature(temp):
local_var.temperature = temp # 每个线程都创建并设置temperature
print_temperature()
输出结果如下:
temperature = 0.500000
AttributeError: '_thread._local' object has no attribute 'temperature'
发现仍旧有错误提示出现,这是因为此时主线程中还没有temperature这个属性,因此不能直接输出。要解决这个问题,我们可以在print_temperature()函数中加入判断:
def print_temperature():
try:
print('temperature = %f' % local_var.temperature)
except AttributeError:
print('No temperature found.')
再次运行程序,输出结果如下:
temperature = 0.500000
No temperature found.
这个输出结果已经符合我们的预期了。我们通过使用Python threading中的Local()函数成功地创建了一个线程局部变量,实现了多线程中安全访问变量的目的。