千家信息网

怎么理解Python中的ThreadLocal变量

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章主要讲解了"怎么理解Python中的ThreadLocal变量",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么理解Python中的Threa
千家信息网最后更新 2026年11月03日怎么理解Python中的ThreadLocal变量

这篇文章主要讲解了"怎么理解Python中的ThreadLocal变量",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么理解Python中的ThreadLocal变量"吧!

只用全局变量并不能满足多线程环境的需求,很多时候线程还需要拥有自己的私有数据,这些数据对于其他线程来说不可见。因此线程中也可以使用局部变量,局部变量只有线程自身可以访问,同一个进程下的其他线程不可访问。

有时候使用局部变量不太方便,因此 python 还提供了 ThreadLocal 变量,它本身是一个全局变量,但是每个线程却可以利用它来保存属于自己的私有数据,这些私有数据对其他线程也是不可见的。下图给出了线程中这几种变量的存在情况:

线程变量

全局 VS 局部变量

首先借助一个小程序来看看多线程环境下全局变量的同步问题。

import threading global_num = 0 def thread_cal():     global global_num     for i in xrange(1000):         global_num += 1 # Get 10 threads, run them and wait them all finished. threads = [] for i in range(10):     threads.append(threading.Thread(target=thread_cal))     threads[i].start() for i in range(10):     threads[i].join() # Value of global variable can be confused. print global_num

这里我们创建了10个线程,每个线程均对全局变量 global_num 进行1000次的加1操作(循环1000次加1是为了延长单个线程执行时间,使线程执行时被中断切换),当10个线程执行完毕时,全局变量的值是多少呢?答案是不确定。简单来说是因为 global_num += 1 并不是一个原子操作,因此执行过程可能被其他线程中断,导致其他线程读到一个脏值。以两个线程执行 +1 为例,其中一个可能的执行序列如下(此情况下***结果为1):

多线程全局变量同步

多线程中使用全局变量时普遍存在这个问题,解决办法也很简单,可以使用互斥锁、条件变量或者是读写锁。下面考虑用互斥锁来解决上面代码的问题,只需要在进行 +1 运算前加锁,运算完毕释放锁即可,这样就可以保证运算的原子性。

l = threading.Lock() ...     l.acquire()     global_num += 1     l.release()

在线程中使用局部变量则不存在这个问题,因为每个线程的局部变量不能被其他线程访问。下面我们用10个线程分别对各自的局部变量进行1000次加1操作,每个线程结束时打印一共执行的操作次数(每个线程均为1000):

def show(num):     print threading.current_thread().getName(), num def thread_cal():     local_num = 0     for _ in xrange(1000):         local_num += 1     show(local_num) threads = [] for i in range(10):     threads.append(threading.Thread(target=thread_cal))     threads[i].start()

可以看出这里每个线程都有自己的 local_num,各个线程之间互不干涉。

Thread-local 对象

上面程序中我们需要给 show 函数传递 local_num 局部变量,并没有什么不妥。不过考虑在实际生产环境中,我们可能会调用很多函数,每个函数都需要很多局部变量,这时候用传递参数的方法会很不友好。

为了解决这个问题,一个直观的的方法就是建立一个全局字典,保存进程 ID 到该进程局部变量的映射关系,运行中的线程可以根据自己的 ID 来获取本身拥有的数据。这样,就可以避免在函数调用中传递参数,如下示例:

global_data = {} def show():     cur_thread = threading.current_thread()     print cur_thread.getName(), global_data[cur_thread] def thread_cal():     cur_thread = threading.current_thread()     global_data[cur_thread] = 0     for _ in xrange(1000):         global_data[cur_thread] += 1     show()  # Need no local variable.  Looks good. ...

保存一个全局字典,然后将线程标识符作为key,相应线程的局部数据作为 value,这种做法并不***。首先,每个函数在需要线程局部数据时,都需要先取得自己的线程ID,略显繁琐。更糟糕的是,这里并没有真正做到线程之间数据的隔离,因为每个线程都可以读取到全局的字典,每个线程都可以对字典内容进行更改。

为了更好解决这个问题,python 线程库实现了 ThreadLocal 变量(很多语言都有类似的实现,比如Java)。ThreadLocal 真正做到了线程之间的数据隔离,并且使用时不需要手动获取自己的线程 ID,如下示例:

global_data = threading.local() def show():     print threading.current_thread().getName(), global_data.num def thread_cal():     global_data.num = 0     for _ in xrange(1000):         global_data.num += 1     show() threads = [] ... print "Main thread: ", global_data.__dict__ # {}

上面示例中每个线程都可以通过 global_data.num 获得自己独有的数据,并且每个线程读取到的 global_data 都不同,真正做到线程之间的隔离。

感谢各位的阅读,以上就是"怎么理解Python中的ThreadLocal变量"的内容了,经过本文的学习后,相信大家对怎么理解Python中的ThreadLocal变量这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

线程 变量 局部 全局 数据 问题 函数 之间 字典 内容 环境 示例 进程 学习 私有 运算 隔离 原子 参数 就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技活动banner 麻工互联网科技 互联网科技金融公司 唐信互联网科技 大连 广西拼得多互联网科技有限公司 银川新华互联网科技学校地址 温州喔噻互联网科技有限公司 小米互联网科技园设置 金融科技与互联网金融相同和不同 互联网科技商业 深圳育鹏互联网科技有限公司招聘 亳州好赞互联网科技有限公司 科技类公司包括互联网吗 民营互联网公司国防科技 威龙国际互联网科技公司 山东子淼互联网科技有限公司 梅州GM互联网络科技有限公司 陕西云淼互联网科技公司 互联网界的黑科技 兰石爱特工业互联网科技分公司 互联网科技上市公司 互联网高科技股票 互联网科技公司介绍 天速互联网络科技有限公司 健康食品互联网创新科技园项目 无锡工业互联网科技有限公司 上海钢联属于互联网科技股吗 领航科技大厦互联网公司 湖北辰鑫科技互联网 科技美学互联网 艺术
0