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()
    复制代码
     
     
    分类: 并发编程
    0
    0
     
     
     
    « 上一篇: 高级算法
    » 下一篇: Flask的上下文源码剖析
  • 相关阅读:
    Atitit 趋势管理之道 attilax著
    Atitit 循环处理的新特性 for...else...
    Atitit 2017年的技术趋势与未来的大技术趋势
    atitit 用什么样的维度看问题.docx 如何了解 看待xxx
    atitit prj mnrs 项目中的几种经理角色.docx
    Atitit IT办公场所以及度假村以及网点以及租房点建设之道 attilax总结
    Atitit 工具选型的因素与方法 attilax总结
    Atitit.团队文化建设影响组织的的一些原理 法则 定理 效应 p826.v4
    Atiitt 管理方面的误区总结 attilax总结
    Atitit 未来趋势把控的书籍 attilax总结 v3
  • 原文地址:https://www.cnblogs.com/du-jun/p/12320720.html
Copyright © 2011-2022 走看看