Pythonでスレッドを使用する方法

Pythonで別スレッドを起動するには、「threading」モジュールを使用します。

import threading

新しいスレッドの実行方法

次のようにして、新しいスレッドを実行します。ただし、スレッドのメソッドは非同期(async)指定していると動作しません。

import threading

def thread_method(param1, param2):
    print(f"Thread running with {param1} and {param2}")

sub_thread = threading.Thread(target=thread_method, args=("param1", "param2"))
sub_thread.start()

このコードでは、thread_methodを別スレッドで実行し、引数として"param1""param2"を渡します。スレッドを開始するためには、start()メソッドを呼び出します。

スレッドの終了を待つ方法

スレッドが終了するまで処理を待つ場合は、join()メソッドを使用します。以下の例では、スレッドが完了するのを待つためにjoin()を追加しています。

import threading

def thread_method():
    for i in range(5):
        print(f"Thread running")

sub_thread = threading.Thread(target=thread_method)
sub_thread.start()
print('main 1')
sub_thread.join()  # スレッドが終了するまで待機
print('main 2')

出力例

Thread running
Thread running
main 1
Thread running
Thread running
Thread running
main 2

join()メソッドを使用することで、メインスレッドはsub_threadが完了するのを待つようになります。これにより、スレッドの実行が完了するまで次の処理に進むことがありません。

この方法は特に、スレッドの結果を使用する必要がある場合や、スレッドが完了するまで他の処理を停止させたい場合に有効です。

スレッド間で処理のバッティングを防ぐ方法

スレッド間で処理のバッティングを防ぎたい場合は、threading.Lock()を使用します。lockオブジェクトを利用することで、クリティカルセクション(複数のスレッドが同時にアクセスすると問題が発生する部分)へのアクセスを制御することができます。

以下は、threading.Lock()を使用してスレッド間の処理のバッティングを防ぐ例です。

import threading

# ロックオブジェクトを作成する
lock = threading.Lock()

# 共有リソース
shared_resource = 0

def thread_method(param1):
    global shared_resource
    # ロックを取得
    with lock:
        # クリティカルセクション
        print(f"Thread {param1} is running")
        shared_resource += 1
        print(f"Shared resource value: {shared_resource}")

# スレッドを作成して起動する
threads = []
for i in range(5):
    thread = threading.Thread(target=thread_method, args=(i,))
    threads.append(thread)
    thread.start()

# 全てのスレッドが完了するのを待つ
for thread in threads:
    thread.join()

このコードでは、lockオブジェクトを使用してthread_method内のクリティカルセクションを保護しています。with lock:ブロック内のコードは、他のスレッドが同じロックを取得するまで実行されません。これにより、共有リソースへの同時アクセスによるデータの不整合を防ぎます。

ロックを正しく使用することで、スレッドセーフなプログラムを実現できます。

Socket.ioサーバでのスレッド起動

Socket.ioサーバを利用する際、バックグラウンドで並列処理を行うためには、start_background_task()メソッドを使用してスレッドを起動します。

import socketio

sio = socketio.AsyncServer(cors_allowed_origins='*', async_mode = 'aiohttp')

sio.start_background_task(background_task, arg1, arg2)

async def background_task(arg1, arg2):
  # process
このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 が付いている欄は必須項目です