Tom*_*Tom 18 python multithreading
我正在读这个问题(你不必阅读,因为我会复制那里的东西......我只是想告诉你我的灵感)......
所以,如果我有一个类来计算创建了多少个实例:
class Foo(object):
instance_count = 0
def __init__(self):
Foo.instance_count += 1
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果我在多个线程中创建Foo对象,instance_count是否正确?类变量是否可以安全地从多个线程修改?
Ant*_*sma 27
即使在CPython上也不是线程安全的.试试这个看看自己:
import threading
class Foo(object):
instance_count = 0
def inc_by(n):
for i in xrange(n):
Foo.instance_count += 1
threads = [threading.Thread(target=inc_by, args=(100000,)) for thread_nr in xrange(100)]
for thread in threads: thread.start()
for thread in threads: thread.join()
print(Foo.instance_count) # Expected 10M for threadsafe ops, I get around 5M
Run Code Online (Sandbox Code Playgroud)
原因是虽然INPLACE_ADD在GIL下是原子的,但属性仍然被加载并存储(参见dis.dis(Foo .__ init __)).使用锁定序列化对类变量的访问:
Foo.lock = threading.Lock()
def interlocked_inc(n):
for i in xrange(n):
with Foo.lock:
Foo.instance_count += 1
threads = [threading.Thread(target=interlocked_inc, args=(100000,)) for thread_nr in xrange(100)]
for thread in threads: thread.start()
for thread in threads: thread.join()
print(Foo.instance_count)
Run Code Online (Sandbox Code Playgroud)
不,它不是线程安全的.我几天前遇到过类似的问题,我选择通过装饰器实现锁定.好处是它使代码可读:
def threadsafe_function(fn):
"""decorator making sure that the decorated function is thread safe"""
lock = threading.Lock()
def new(*args, **kwargs):
lock.acquire()
try:
r = fn(*args, **kwargs)
except Exception as e:
raise e
finally:
lock.release()
return r
return new
class X:
var = 0
@threadsafe_function
def inc_var(self):
X.var += 1
return X.var
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10621 次 |
| 最近记录: |