import threading
shared_balance = 0
class Deposit(threading.Thread):
def run(self):
for i in xrange(1000000):
global shared_balance
balance = shared_balance
balance += 100
shared_balance = balance
class Withdraw(threading.Thread):
def run(self):
for i in xrange(1000000):
global shared_balance
balance = shared_balance
balance -= 100
shared_balance = balance
thread1 = Deposit()
thread2 = Withdraw()
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print shared_balance
每次我运行这个程序时,它都会输出一个随机数。如果存入 100、100 万次,取款 100、100 万次,为什么输出不是 0?
请您参考如下方法:
您需要使用 threading.Lock安全地访问你的变量:
from threading import Thread, Lock
shared_balance = 0
class Deposit(Thread):
def __init__(self, lock):
super(Deposit, self).__init__()
self.lock = lock
def run(self):
global shared_balance
for i in xrange(1000000):
with self.lock:
shared_balance += 100
class Withdraw(Thread):
def __init__(self, lock):
super(Withdraw, self).__init__()
self.lock = lock
def run(self):
global shared_balance
for i in xrange(1000000):
with self.lock:
shared_balance -= 100
shared_lock = Lock()
thread1 = Deposit(shared_lock)
thread2 = Withdraw(shared_lock)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print shared_balance
输出:
>>> 0
另外,看看为以下内容生成的字节码:
a = 0
def f():
global a
a += 10
“a += 10”的字节码:
6 LOAD_GLOBAL 0 (a) # Load global "a" UNSAFE ZONE
9 LOAD_CONST 2 (10) # Load value "10" UNSAFE ZONE
12 INPLACE_ADD # Perform "+=" UNSAFE ZONE
13 STORE_GLOBAL 0 (a) # Store global "a"
16 LOAD_CONST 0 (None) # Load "None"
19 RETURN_VALUE # Return "None"
在 Python 中,字节码的执行不能被抢占。它使线程使用起来非常方便。但在那种情况下,执行“+=”操作需要执行 4 次字节码。这意味着任何其他线程的任何其他字节码都易于在这些字节码之间执行。这就是它不安全的原因,也是您应该使用锁的原因。
