美文网首页
Python 本地线程对象threading.local类

Python 本地线程对象threading.local类

作者: 忘了呼吸的那只猫 | 来源:发表于2019-05-22 15:15 被阅读0次

在使用threading.local()之前,先了解一下局部变量和全局变量。

局部变量:

import threading
import time
 
def worker():
    x = 0
    for i in range(100):
        time.sleep(0.0001)
        x += 1
    print(threading.current_thread(),x)
 
for i in range(10):
    threading.Thread(target=worker).start()
 
运行结果:
<Thread(Thread-2, started 123145372971008)> 100
<Thread(Thread-6, started 123145393991680)> 100
<Thread(Thread-1, started 123145367715840)> 100
<Thread(Thread-3, started 123145378226176)> 100
<Thread(Thread-5, started 123145388736512)> 100
<Thread(Thread-7, started 123145399246848)> 100
<Thread(Thread-4, started 123145383481344)> 100
<Thread(Thread-10, started 123145415012352)> 100
<Thread(Thread-8, started 123145404502016)> 100
<Thread(Thread-9, started 123145409757184)> 100

上面例子使用多线程,每个子线程完成不同的计算任务,x是局部变量。

每个子线程都要压栈,每个栈是独立的空间。每次压栈,局部变量x的作用域地址是不同的(线程独享),计算结果互不干扰。

全局变量:

使用global:

import threading
import time
 
x = 0
def worker():
    global x
    x = 0
    for i in range(100):
        time.sleep(0.0001)
        x += 1
    print(threading.current_thread(),x)
 
for i in range(10):
    threading.Thread(target=worker).start()
 
运行结果:
<Thread(Thread-2, started 123145483571200)> 888
<Thread(Thread-5, started 123145499336704)> 908
<Thread(Thread-3, started 123145488826368)> 930
<Thread(Thread-4, started 123145494081536)> 937
<Thread(Thread-1, started 123145478316032)> 941
<Thread(Thread-6, started 123145504591872)> 947
<Thread(Thread-7, started 123145509847040)> 949
<Thread(Thread-8, started 123145515102208)> 955
<Thread(Thread-9, started 123145520357376)> 962
<Thread(Thread-10, started 123145525612544)> 964

上面例子中当主线程中x是全局变量时,就变成了公共资源(也就是同一个对象),每个子线程互相干扰,最终导致错误的计算结果。

Python提供了 threading.local 类,将这个类实例化得到一个全局对象,但是不同的线程使用这个对象存储的数据其它线程不可见(本质上就是不同的线程使用这个对象时为其创建一个独立的字典)。

使用threading.local() :

import threading
import time
 
# class A:
#     def __init__(self,x):
#         self.x = x
# a = A(0)
 
a = threading.local()#全局对象
 
def worker():
    a.x = 0
    for i in range(100):
        time.sleep(0.0001)
        a.x += 1
    print(threading.current_thread(),a.x)
 
for i in range(10):
    threading.Thread(target=worker).start()
 
运行结果:
<Thread(Thread-4, started 123145570172928)> 100
<Thread(Thread-6, started 123145580683264)> 100
<Thread(Thread-1, started 123145554407424)> 100
<Thread(Thread-2, started 123145559662592)> 100
<Thread(Thread-8, started 123145591193600)> 100
<Thread(Thread-5, started 123145575428096)> 100
<Thread(Thread-3, started 123145564917760)> 100
<Thread(Thread-7, started 123145585938432)> 100
<Thread(Thread-10, started 123145601703936)> 100
<Thread(Thread-9, started 123145596448768)> 100

每个子线程使用全局对象a,但每个线程定义的属性a.x是该线程独有的。

举一个错误的例子:,主线程中使用threading.local定义本地变量x,x在主线程中是独有的,子线程中就访问不到主线程的x的属性。

import threading
 
X='abc'
ctx=threading.local()
ctx.x=123 #主线程中定义x本地属性
print(ctx,type(ctx),ctx.x)
 
def work():
    print(X)
    print(ctx)
    print(ctx.x) #子线程访问不到
    print('Good job')
 
threading.Thread(target=work).start()
运行结果:
<_thread._local object at 0x10407bd00> <class '_thread._local'> 123
abc
<_thread._local object at 0x10407bd00>
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Users/ihoney/Python/test_4.py", line 12, in work
    print(ctx.x)
AttributeError: '_thread._local' object has no attribute 'x'

ctx全局对象对主线程和子线程都是可以使用的,主线程定义了属性x,但子线程在尝试访问属性x时,就相当于访问自己线程内的属性x,而自己线程并没有定义,就会抛出AttributeError异常:'_thread._local' object has no attribute 'x'

相关文章

  • Python 本地线程对象threading.local类

    在使用threading.local()之前,先了解一下局部变量和全局变量。 局部变量: 上面例子使用多线程,每个...

  • 本地线程-数据库连接池的应用

    threading.local函数可以创建线程本地数据空间,其下属性对每个线程独立存在,先看一段代码 以DButi...

  • 数据库连接池

    知识储备: 本地线程 模式一 基于threading.local为每个线程创建一个连接con。 连接关闭时不是真的...

  • Flask上下文机制

    预备知识: 本地线程 我们要在同一个进程中隔离不同线程的数据,那么我们会优先选择threading.local,来...

  • Python 多线程

    开始学习Python线程 Python中使用线程有两种方式:函数或者用类来包装线程对象。 函数式:调用thread...

  • ​Python 多进程大全

    开始学习Python线程 Python中使用线程有两种方式:函数或者用类来包装线程对象。 函数式:调用thread...

  • Flask拾遗笔记之上下文

    0x01 背景知识 threading.local() 通过threading.local()可以创建一个线程安全...

  • 12.ThreadLocal类的使用和实现原理

    ThreadLocal ThreadLocal,顾名思义就是线程本地对象,理解起来就是线程局部变量,这个类可以将对...

  • 线程

    Python基础教程 在python中有两种线程的操作方式:函数或者用类来包装线程对象 用函数 使用 thread...

  • python ‘多线程’

    python 的多线程是通过 threading 模块的 Thread 类来实现的。 创建线程对象t1 = thr...

网友评论

      本文标题:Python 本地线程对象threading.local类

      本文链接:https://www.haomeiwen.com/subject/hdkuzqtx.html