1. ホーム
  2. python

マルチスレッドのPythonコードでロックが不要なのはGILのせい?

2023-08-18 05:33:12

質問

Global Interpreter Lock を持つ Python の実装 (CPython など) に依存し、マルチスレッドコードを書いている場合、本当にロックは全く必要ないのでしょうか?

GILが複数の命令の並列実行を許さないのであれば、共有データの保護は不要ではないでしょうか?

馬鹿な質問で申し訳ないのですが、マルチプロセッサ/コアマシンでのPythonについていつも疑問に思っていることなのです。

同じことが、GILを持つ他のどのような言語実装にも当てはまります。

どのように解決するのですか?

スレッド間で状態を共有する場合にもロックは必要です。GIL はインタープリタを内部的に保護するだけです。独自のコードで一貫性のない更新が行われる可能性があります。

例えば

#!/usr/bin/env python
import threading

shared_balance = 0

class Deposit(threading.Thread):
    def run(self):
        for _ in xrange(1000000):
            global shared_balance
            balance = shared_balance
            balance += 100
            shared_balance = balance

class Withdraw(threading.Thread):
    def run(self):
        for _ in xrange(1000000):
            global shared_balance
            balance = shared_balance
            balance -= 100
            shared_balance = balance

threads = [Deposit(), Withdraw()]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

print shared_balance

ここでは、共有状態を読み込む間にコードを割り込ませることができます ( balance = shared_balance ) と変更された結果を書き戻す ( shared_balance = balance )、更新の失敗を引き起こします。その結果、共有状態にはランダムな値が設定されます。

更新を一貫したものにするために、ランメソッドはリード・モディファイ・ライトセクションの周り(ループの中)で共有状態をロックするか、または 共有状態が読み込まれてから変更されたときにそれを検出する何らかの方法 .