1
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 にならないのはなぜですか?

4

5 に答える 5

1

ここからhttp://effbot.org/zone/thread-synchronization.htm

これは、インクリメント/デクリメント操作が実際には 3 つのステップで実行されるためです。最初に、インタープリターはカウンターの現在の値をフェッチし、次に新しい値を計算し、最後に新しい値を変数に書き戻します。

現在のスレッドが変数をフェッチした後に別のスレッドが制御を取得した場合、現在のスレッドが同じことを行う前に、別のスレッドが変数をフェッチし、インクリメントして、書き戻すことがあります。どちらも元の値が同じであるため、1 つの項目のみが考慮されます。

于 2013-11-12T08:47:04.117 に答える
1

リーダーライターの問題だと思う

あなたの問題はここにあるようです:

balance = shared_balance
balance += 100

次の実行順序がある場合、何が起こるか考えてみてください。

[...]
deposit thread:    balance = shared_balance
withdraw thread:   balance -= 100
deposit thread:    balance += 100
deposit thread:    shared_balance = balance
withdraw thread:   shared_balance = balance

shared_balance の更新が失われました

于 2013-11-12T08:47:54.780 に答える
1

Try lock.acquire() and lock.release() to fix your problem:

sorry for duplicating some code. I have marked the changes:

lock = threading.Lock()
class Deposit(threading.Thread):
  def run(self):
    for i in xrange(1000000):
      lock.acquire()               <==============================
      global shared_balance
      balance = shared_balance
      #print "[thread1] old: " + str(balance)
      balance += 100
      #print "[thread1] new: " + str(balance)
      shared_balance = balance
      #print "[thread1] shared: " + str(shared_balance)
      lock.release()               <==============================

class Withdraw(threading.Thread):
  def run(self):
    for i in xrange(1000000):
      lock.acquire()              <==============================
      global shared_balance
      balance = shared_balance
      #print "[thread2] old: " + str(balance)
      balance -= 100
      #print "[thread2] new: " + str(balance)
      shared_balance = balance
      #print "[thread2] shared: " + str(shared_balance)
      lock.release()              <==============================**
于 2013-11-12T08:53:24.463 に答える