マルチスレッドの競合
マルチスレッド環境だと、1つのリソースや変数などに複数のスレッドから同時にアクセスすると、その変数がおかしな値になってしまいます。
競合が起きるプログラム
1 から 100 万をカウントするプログラムです。
3つのスレッドで動かすので期待する値は 3000000 です.
import threading
class Counter:
def __init__(self):
self.count = 0
def count_up_million(self):
for _ in range(1000000):
self.count += 1
def worker(counter):
counter.count_up_million()
def main():
counter = Counter()
threads = []
for _ in range(3):
thread = threading.Thread(target=worker, args=(counter,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print(counter.count)
if __name__ == '__main__':
main()
結果
1539515
変な数字になる
排他制御(Lock)
同時にアクセスしてもデータの整合性を保つために行う制御が排他制御(Lock)です。
先ほどのプログラムに Lock を用いる
先ほど期待した結果が出なかったプログラムに Lock をするように修正しました。
import threading
class Counter:
def __init__(self):
self.count = 0
self.lock = threading.Lock()
def count_up_million(self):
for _ in range(1000000):
with self.lock:
self.count += 1
def worker(counter):
counter.count_up_million()
def main():
counter = Counter()
threads = []
for _ in range(3):
thread = threading.Thread(target=worker, args=(counter,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print(counter.count)
if __name__ == '__main__':
main()
結果
3000000
無事に 3000000 が出力されました 👏