多线程抢占问题
import time import threading obj = 5 def task(arg): global obj obj = arg time.sleep(1) print(obj) for i in range(6): t = threading.Thread(target=task, args=(i,)) t.start() # 结果 5 5 5 5 5 5
threading.local对象避免线程抢占
为每个线程开辟一块内存空间,存储各自的数据
import time import threading obj = threading.local() def task(arg): global obj obj.value = arg time.sleep(1) print(obj.value) for i in range(6): t = threading.Thread(target=task, args=(i,)) t.start() # 结果 0 3 4 5 2 1
模拟threading.local
import time import threading # 获取线程的唯一标识 from threading import get_ident class Local(): def __init__(self): self.storage = {} def __setitem__(self, key, value): ident = get_ident() if ident in self.storage: self.storage[ident][key] = value else: self.storage[ident] = {key:value} def __getitem__(self, item): ident = get_ident() return self.storage[ident][item] obj = Local() def task(arg): obj['num'] = arg time.sleep(1) print(obj['num']) for i in range(6): t = threading.Thread(target=task, args=(i,)) t.start()
粒度精确到协程
为每个协程开辟一块内存空间,存储各自的数据
import time import threading try: # 获取协程的唯一标识 from greenlet import getcurrent as get_ident except Exception as e: from threading import get_ident class Local(): def __init__(self): self.storage = {} def __setitem__(self, key, value): ident = get_ident() if ident in self.storage: self.storage[ident][key] = value else: self.storage[ident] = {key:value} def __getitem__(self, item): ident = get_ident() try: return self.storage[ident][item] except Exception as e: return None obj = Local() def task(arg): obj['num'] = arg time.sleep(1) print(obj['num']) for i in range(6): t = threading.Thread(target=task, args=(i,)) t.start()