Threading.local

作用

为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。

import threading
from threading import local
import time

obj = local()


def task(i):
	obj.xxxxx = i
	time.sleep(2)
	print(obj.xxxxx,i)

for i in range(10):  #开启了10个线程
	t = threading.Thread(target=task,args=(i,))
	t.start()

如何获取一个线程的唯一标记? 

线程:threading.get_ident()

协程:greenlet.getcurrent()

根据字典自定义一个类似于threading.local功能?

import time
import threading

DIC = {}

def task(i):
	ident = threading.get_ident()
	if ident in DIC:
		DIC[ident]['xxxxx'] = i
	else:
		DIC[ident] = {'xxxxx':i }
	time.sleep(2)

	print(DIC[ident]['xxxxx'],i)

for i in range(10):   #开启了10个线程
	t = threading.Thread(target=task,args=(i,))
	t.start()

根据字典自定义一个为每个协程开辟空间进行存取数据。

import time
import threading
import greenlet

DIC = {}

def task(i):
	
	# ident = threading.get_ident()
	ident = greenlet.getcurrent()
	if ident in DIC:
		DIC[ident]['xxxxx'] = i
	else:
		DIC[ident] = {'xxxxx':i }
	time.sleep(2)

	print(DIC[ident]['xxxxx'],i)

for i in range(10):   #开启了10个线程
	t = threading.Thread(target=task,args=(i,))
	t.start()

通过getattr/setattr 构造出来 threading.local的加强版(协程)

import time
import threading
try:
	import greenlet
	get_ident =  greenlet.getcurrent   #协程    get_ident相当于全局变量
except Exception as e:
	get_ident = threading.get_ident    #线程
  
class Local(object):
	DIC = {}

	def __getattr__(self, item):
		ident = get_ident()
		if ident in self.DIC:
			return self.DIC[ident].get(item)
		return None

	def __setattr__(self, key, value):
		ident = get_ident()
		if ident in self.DIC:
			self.DIC[ident][key] = value
		else:
			self.DIC[ident] = {key:value}
		

obj = Local()

def task(i):
	obj.xxxxx = i
	time.sleep(2)
	print(obj.xxxxx,i)

for i in range(10):       #开启了10个线程
	t = threading.Thread(target=task,args=(i,))
	t.start()

为什么要做数据隔离?

每个人请求需要做数据隔离,不然会出现数据混乱。每个请求数据不同,需要放在不同的空间,根据线程不同,取不同的值。

真正请求来了之后,会通过local对象为他创造一块空间,每个请求来都会做个数据隔离

原文地址:https://www.cnblogs.com/gaoya666/p/9180421.html