Raspberry Pi & Python 開発ブログ ☆彡

Raspberry PiとPythonの基本的な使い方をわかりやすく解説。初心者、入門者必見!!

python3:Thread(スレッド)で排他制御をする

thread lock

ブログ管理者のP.Hです!

今回はスレッドで排他制御する方法を紹介したいと思います。異なるスレッドから同タイミングで処理を衝突させたくない場合、排他制御を行うことで回避できます。

それでは排他制御の実装の仕方を説明していきます。

threading.Lockモジュールの使い方

排他制御は、下記のようにLock()モジュールを使用します。

threading.Lock().acquire()

排他制御したいコード

threading.Lock().release()

注意しなければいけないことは、排他制御したいコードの処理時間が長いと、その期間はブロック状態となり順次処理となりますので、処理時間が長くなります。ですので、排他制御を行う部分は最小限にしましょう。排他制御をしている方が安全だからといって、大きな範囲で排他制御を行ってしまっては並列処理をしている意味がありません。

python:サンプルコード

from concurrent.futures import ThreadPoolExecutor 
import time
import threading

class Lock1:

    def __init__(self, l):
        self.l = l

    def run(self):
        while True:
            self.l.acquire() # 排他制御開始
            print("Lock1 : lock acquire")
            time.sleep(1)
            print("Lock1 : lock release")
            self.l.release() # 排他制御解除
            time.sleep(1)

class Lock2:

    def __init__(self, l):
        self.l = l
    
    def run(self):
        while True:
            self.l.acquire() # 排他制御開始
            print("Lock2 : lock acquire")
            time.sleep(1)
            print("Lock2 : lock release")
            self.l.release() # 排他制御解除
            time.sleep(1)

if __name__ == "__main__":
    
    lock = threading.Lock() # Lockモジュール生成
    th_pool = []
    th_pool.append(Lock1(lock).run) # 各スレッドにLockモジュールを引数として渡す
    th_pool.append(Lock2(lock).run) # 各スレッドにLockモジュールを引数として渡す
    
    with ThreadPoolExecutor(max_workers=2) as executor: 
        for th in th_pool:
            executor.submit(th) # スレッド生成

結果は以下のようになります。Lock1 acqure ⇒ release 、Lock2 acqure ⇒ release の順番が守られていることがわかります。

Lock1 : lock acquire
Lock1 : lock release
Lock2 : lock acquire
Lock2 : lock release
Lock1 : lock acquire
Lock1 : lock release
Lock2 : lock acquire
Lock2 : lock release
Lock1 : lock acquire
Lock1 : lock release

self.l.acquire() と`self.l.release()をコメントアウトして実行してみましょう。結果は以下のようになります。Lock1 acqure ⇒ release の間にLock2の処理が入ってしまうことがわかります。

Lock1 : lock acquire
Lock2 : lock acquire
Lock1 : lock release
Lock2 : lock release
Lock1 : lock acquire
Lock2 : lock acquire
Lock1 : lock release
Lock2 : lock release
Lock1 : lock acquire
Lock2 : lock acquire

以上で排他制御の説明は終了です。

pythonに戻る
トップページに戻る