假如,开了十个线程而且作一样的一件事,他们须要带着本身的数据进来,完成事情后带着本身的数据出去。若是是并发,同时进来,他们的数据就会混乱。并发
通常状况,咱们加锁就能够了,一我的先进来,先加锁,另外一我的过来看到加锁了,就在外面等,等里面的人出来,本身进去加锁,这样就不会出现数据混乱的问题。ide
另外一种解决方法就是threading.local()来解决问题。spa
先看下面这个现象线程
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更改后的值,若是很是快,他们取到的值都不同.code
若是让他们睡两秒再执行对象
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
打印结果全是9blog
那么解决这个问题咱们能够用threading.local()方法get
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()