threading.local学习

多线程抢占问题

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()