即使在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
的原因是,雖然INPLACE_ADD是GIL下原子的屬性仍然加載和存儲(請dis.dis(富.__ 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)
是Foo.instance_count + = 1和原子工作單元? – 2009-07-02 07:01:10
也許我不明白GIL是如何工作的......但我仍然沒有看到它。不能線程1讀取instance_count。然後thread1停止。線程2讀取instance_count,然後停止。線程1修改和寫入。線程2寫入。所以你失去了一個增量? GIL如何確保線程貫穿整個+ =操作? – Tom 2009-07-02 07:02:36
哈,我基本上是問薩姆弗蘭在我面前問什麼。 – Tom 2009-07-02 07:03:10