• python之threading.local


    简述:

    threading.local是全局变量但是它的值却在当前调用它的线程当中

    作用:

    在threading module中,有一个非常特别的类local。一旦在主线程实例化了一个local,它会一直活在主线程中,并且又主线程启动的子线程调用这个local实例时,它的值将会保存在相应的子线程的字典中。可以为每个线程创建一块独立的空间,让他存放数据。

    使用方式:

    在使用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

    全局变量:

    使用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'。

  • 相关阅读:
    C# 实现 JAVA AES加密解密(转他人)
    转 Java、C#双语版配套AES加解密示例
    开发工具资料
    WebApi返回Json格式
    【转】NuGet.org 无法访问的解决方法
    使用Senparc.Weixin.WxOpen开发高可用的微信小程序
    WebApi资料
    WinForm资料
    Winform开发框架之终极应用
    Winform开发中另一种样式的OutLookBar工具条
  • 原文地址:https://www.cnblogs.com/wangshuyang/p/8929598.html
Copyright © 2020-2023  润新知