python 线程安全
1 线程抢占
import time
from threading import Thread
class Foo(object):
pass
f = Foo()
f.num = 0
def add(i):
f.num = i
time.sleep(1)
print(f.num)
for i in range(20):
task = Thread(target=add, args=(i,))
task.start()
- 由于本例中f对象为公共对象,当多线程去操作同一个对象时,就会发生线程抢占
- 输出:结果为20个19
2 解决线程抢占
2.1 以增加空间的方式解决
import time
from copy import deepcopy
from threading import Thread,get_ident
class Foo(object):
pass
f = Foo()
f.num = 0
tmp_thread_dict = {}
def add(i):
# 通过每个线程中get_ident的唯一性,使每个线程使用独立的内存空间运行,以确保线程安全
tmp_thread_dict[get_ident()] = deepcopy(f)
tmp_thread_dict[get_ident()].num = i
time.sleep(1)
print(tmp_thread_dict[get_ident()].num)
for i in range(20):
task = Thread(target=add, args=(i,))
task.start()
2.2 线程local属性
- 极快的解决阻塞,保证公共对象的安全性
- 浪费很小的资源
import time
from threading import Thread, local
class Foo(local):
pass
f = Foo()
f.num = 0
def add(i):
f.num = i
time.sleep(1)
print(f.num)
for i in range(20):
task = Thread(target=add, args=(i,))
task.start()