ルール
共有状態への スレッドセーフな アクセスを 確保してください。
複数の スレッドによって 同期なしで アクセスされる 共有の 可変状態は
レースコンディションや ランタイムエラーを 引き起こします。
サポート言語: Python、 Java、 C#はじめに
複数のスレッドが同期なしに共有変数にアクセスし変更すると、競合状態が発生します。最終的な値は予測不能なスレッド実行タイミングに依存し、データ破損、誤った計算、またはランタイムエラーを引き起こします。ロックなしに複数のスレッドによってインクリメントされるカウンターは、スレッドが古い値を読み取り、インクリメントし、競合する結果を書き戻すため、更新を見逃します。
なぜ重要なのか
データ破損と不正確な結果: 競合状態は、値が不整合または不正確になるサイレントなデータ破損を引き起こします。アカウント残高が誤っていたり、在庫数がマイナスになったり、集計統計が破損したりする可能性があります。これらのバグは、正確なスレッドタイミングに依存するため、再現が困難です。
システムの不安定性: 共有状態への非同期アクセスはアプリケーションをクラッシュさせる可能性があります。あるスレッドがデータ構造を変更している間に別のスレッドがそれを読み取ると、ヌルポインタエラーやインデックス範囲外などの例外が発生します。本番環境では、これらは負荷がかかった際の断続的なクラッシュとして現れます。
デバッグの複雑さ: 競合状態は非決定性であるため、デバッグが非常に困難です。シングルスレッドテストや低負荷環境ではバグが発生しない場合があります。再現には強制が難しい特定の実行スレッドのインターリーブが必要であり、問題がランダムに発生したり消えたりします。
コード例
❌ 非準拠:
class BankAccount:
def __init__(self):
self.balance = 0
def deposit(self, amount):
current = self.balance
# 競合状態:ここで別のスレッドが残高を変更する可能性があります
time.sleep(0.001) # 処理時間をシミュレート
self.balance = current + amount
def withdraw(self, amount):
if self.balance >= amount:
current = self.balance
time.sleep(0.001)
self.balance = current - amount
return True
return False
誤っている理由: 複数のスレッドが同時に deposit() または withdraw() を呼び出すと、競合状態が発生します。それぞれ100ドルを預金する2つのスレッドが、両方とも残高を0ドルと読み取り、その後両方とも100ドルを書き込むことで、最終的な残高が200ドルではなく100ドルになる可能性があります。
✅ 準拠済み:
import threading
class BankAccount:
def __init__(self):
self.__balance = 0
self.__lock = threading.Lock()
@property
def balance(self):
with self.__lock:
return self.__balance
def deposit(self, amount):
with self.__lock:
current = self.__balance
time.sleep(0.001)
self.__balance = current + amount
def withdraw(self, amount):
with self.__lock:
if self.__balance >= amount:
current = self.__balance
time.sleep(0.001)
self.__balance = current - amount
return True
return False
これが重要である理由: 会社情報 threading.Lock() 一度に1つのスレッドのみがバランスにアクセスすることを保証します。1つのスレッドがロックを保持している間、他のスレッドは待機し、同時変更を防ぎます。プライベート __balance readonlyで @property 外部コードによるロック保護のバイパスを防止します。
まとめ
すべての共有可能な可変状態を、ロック、セマフォ、アトミック操作などの適切な同期プリミティブで保護します。可能な場合は、イミュータブルなデータ構造またはスレッドローカルストレージを優先してください。同期が必要な場合は、競合を減らしパフォーマンスを向上させるために、クリティカルセクションを最小限に抑えます。

