zoukankan      html  css  js  c++  java
  • 多线程局部变量之threading.local()用法

    假如,开了十个线程并且做同样的一件事,他们需要带着自己的数据进来,完成事情后带着自己的数据出去。如果是并发,同时进来,他们的数据就会混乱。

    一般情况,我们加锁就可以了,一个人先进来,先加锁,另一个人过来看到加锁了,就在外面等,等里面的人出来,自己进去加锁,这样就不会出现数据混乱的问题。

    另一种解决方法就是threading.local()来解决问题。

    先看下面这个现象

    from threading import Thread
    
    ret = -1  # 先定义一个变量
    
    
    def task(arg):  # 写个任务,加个参数
        global ret  # 声明ret全局变量
        ret = arg  # 每一个线程进来到要改这个变量
        print(ret)  # 每个线程来,改了ret,然后取ret的值
    
    
    for i in range(10):  # i是线程的值,0 1 2 3 4 5 6 7 8 9
        t = Thread(target=task, args=(i,))  # 开10个线程
        t.start()
    # 打印结果 0 1 2 3 4 5 6 7 8 9

    这个程序开了10个线程,每个线程都执行了更改ret的值并获取ret更改后的值,如果非常快,他们取到的值都不一样.

    如果让他们睡两秒再执行

    from threading import Thread
    import time
    
    ret = -1  # 先定义一个变量
    
    
    def task(arg):  # 写个任务,加个参数
        global ret  # 声明ret全局变量
        ret = arg  # 每一个线程进来到要改这个变量
        time.sleep(2)
        print(ret)  # 每个线程来,改了ret,然后取ret的值
    
    
    for i in range(10):  # i是线程的值,0 1 2 3 4 5 6 7 8 9
        t = Thread(target=task, args=(i,))  # 开10个线程
        t.start()
    # 打印结果 9 9 9 9 9 9 9 9 9 9

    打印结果全是9

    那么解决这个问题我们可以用threading.local()方法

    from threading import Thread
    from threading import local
    import time
    # 这是一个特殊的对象
    ret = local()  # 先实例化一个对象
    
    
    def task(arg):  # 写个任务,加个参数
        ret = arg  # 每一个线程进来都给他开辟一个独立的空间  单纯的threading.local()的作用就是这个
        time.sleep(2)
        print(ret)  # 每个线程来,改了ret,然后取ret的值
    
    
    for i in range(10):  # i是线程的值,0 1 2 3 4 5 6 7 8 9
        t = Thread(target=task, args=(i,))  # 开10个线程
        t.start()
    # 打印结果 0 3 2 5 7 9 8 4 1 6
    threading.local()的作用就是为每个线程开辟一个独立的空间进行数据存储。

    接下来我们自定义local对象
    from threading import get_ident,Thread
    import time
    
    storage = {}
    
    
    def set(k,v):  # 来给storage设置值
        ident = get_ident()  # get_ident()能获取唯一标识,是一组数字
        if ident in storage:
            storage[ident][k] = v
        else:
            storage[ident] = {k:v}
    
    
    def get(k):  # 来取storage的值
        ident = get_ident()
        return storage[ident][k]
    
    
    def task(arg):
        set('val',arg)
        v = get('val')
        print(v)
    
    
    for i in range(10):
        t = Thread(target=task,args=(i,))
        t.start()
  • 相关阅读:
    洛谷P4768 [NOI2018]归程(可持久化并查集,最短路)
    FFT/NTT总结+洛谷P3803 【模板】多项式乘法(FFT)(FFT/NTT)
    洛谷P2480 [SDOI2010]古代猪文(费马小定理,卢卡斯定理,中国剩余定理,线性筛)
    洛谷P4035 [JSOI2008]球形空间产生器(高斯消元)
    洛谷P2054 [AHOI2005]洗牌(扩展欧几里德)
    洛谷P3868 [TJOI2009]猜数字(中国剩余定理,扩展欧几里德)
    洛谷P1516 青蛙的约会(扩展欧几里德)
    Heaven of Imaginary(PKUSC2018)
    二进制高精度模板(高精度)
    洛谷UVA12995 Farey Sequence(欧拉函数,线性筛)
  • 原文地址:https://www.cnblogs.com/aaronthon/p/9457330.html
Copyright © 2011-2022 走看看