from threading import Thread
import time
num =-1deftask(arg):global num
num = arg
time.sleep(1)print(num)for i inrange(10):
t = Thread(target=task, args=(i,))
t.start()# 每次打印结果都是9
(2)使用local
# local是种特殊的对象,不同线程操作它,操作的是线程自己的,不会出现并发安全问题from threading import Thread
from threading import local
import time
num = local()deftask(arg):
num.value = arg
time.sleep(1)print(num.value)for i inrange(10):
t = Thread(target=task, args=(i,))
t.start()
(3)自己写个低配local对象
from threading import get_ident, Thread
import time
storage ={}# storage的格式为{线程id号1:{k:v}, 线程id号2:{k:v}, ...}defset(k, v):
ident = get_ident()# 获取线程id号if ident in storage:
storage[ident][k]= v
else:
storage[ident]={k: v}defget(k):
ident = get_ident()return storage[ident][k]deftask(arg):set('val', arg)
time.sleep(1)
v = get('val')print(v)for i inrange(10):
t = Thread(target=task, args=(i,))
t.start()
(4) 用面向对象重写local
from threading import get_ident, Thread
import time
classLocal(object):
storage ={}defset(self, k, v):
ident = get_ident()if ident in Local.storage:
Local.storage[ident][k]= v
else:
Local.storage[ident]={k: v}defget(self, k):
ident = get_ident()return Local.storage[ident][k]
obj = Local()deftask(arg):
obj.set('val', arg)
time.sleep(1)
v = obj.get('val')print(v)for i inrange(10):
t = Thread(target=task, args=(i,))
t.start()
(5) 面向对象版本,通过getattr取值、setattr赋值
from threading import get_ident, Thread
import time
classLocal(object):
storage ={}def__setattr__(self, k, v):
ident = get_ident()if ident in Local.storage:
Local.storage[ident][k]= v
else:
Local.storage[ident]={k: v}def__getattr__(self, k):
ident = get_ident()return Local.storage[ident][k]
obj = Local()deftask(arg):
obj.val = arg
time.sleep(1)print(obj.val)for i inrange(10):
t = Thread(target=task, args=(i,))
t.start()# 缺陷在于:每个线程实例化得到的都是同一个storage字典
(6)改良版本(不同的local对象使用自己的字典)
try:from greenlet import getcurrent as get_ident
except Exception as e:from threading import get_ident
# 加上上面的代码就可以处理多协程的并发安全问题,getcurrent方法是取协程号的 from threading import Thread
import time
classLocal(object):def__init__(self):# self.storage = {} # setattr(self, 'storage', {}) # Local.__setattr__(self, 'storage', {})# 上面三种方式都会造成递归调用,不能用object.__setattr__(self,'storage',{})def__setattr__(self, k, v):
ident = get_ident()if ident in self.storage:
self.storage[ident][k]= v
else:
self.storage[ident]={k: v}def__getattr__(self, k):
ident = get_ident()return self.storage[ident][k]
obj = Local()deftask(arg):
obj.val = arg
time.sleep(1)print(obj.val)for i inrange(10):
t = Thread(target=task, args=(i,))
t.start()