1. threading.local对象,用于为每个线程开辟一块空间来保存它独有的值。
Flask的上下文管理借助了这个思想。Thread-local data is data whose values are thread specific
import threading
# class Foo(object):
# def __init__(self):
# self.name = 0
#
# local_values = Foo()
local_values = threading.local()
def func(num):
local_values.name = num
import time
time.sleep(1)
print(local_values.name, threading.current_thread().name)
for i in range(20):
th = threading.Thread(target=func, args=(i,), name='线程%s' % i)
th.start()
如果解注释class Foo,不用threading.local(),那么
因为修改的值始终保存在同一个对象里面,sleep一秒后,全部线程执行完毕,值变成了最后的值19。
2. 单进程单线程多协程中,threading.local会出问题,因为协程数据都存在同一个线程里。
解决方法为:
单进程单线程多协程中,程序不再支持协程,就可以使用threading.local对象。
单进程单线程多协程中,程序想支持协程,那么自定义类似threading.local对象。如下所示
"""
{
identification:{k:v}
}
"""
import threading
try:
from greenlet import getcurrent as get_ident # 协程
except ImportError:
try:
from thread import get_ident
except ImportError:
from _thread import get_ident # 线程
class Local(object):
def __init__(self):
self.storage = {}
self.get_ident = get_ident
def set(self,k,v):
ident = self.get_ident()
origin = self.storage.get(ident)
if not origin:
origin = {k:v}
else:
origin[k] = v
self.storage[ident] = origin
def get(self,k):
ident = self.get_ident()
origin = self.storage.get(ident)
if not origin:
return None
return origin.get(k,None)
local_values = Local()
def task(num):
local_values.set('name',num)
import time
time.sleep(1)
print(local_values.get('name'), threading.current_thread().name)
for i in range(20):
th = threading.Thread(target=task, args=(i,),name='线程%s' % i)
th.start()