17.9. _thread — 低水準の スレッド API


このモジュールはマルチスレッド (別名 軽量プロセス (light-weight processes)または タスク (tasks)) に用いられる低水準プリミティブを提供します — グローバルデータ空間を共有するマルチスレッドを制御します。同期のための単純なロック (別名 mutexes またはバイナリセマフォ (binary semaphores))が提供されています。 threading モジュールは、このモジュール上で、より使い易く高級なスレッディングの API を提供します。

このモジュールはオプションです。 Windows、Linux、SGI IRIX、Solaris 2.x、そして POSIX スレッド (別名 “pthread”) を実装するシステム上でサポートされます。 _thread を使用することのできないシステムでは、 _dummy_thread が用意されています。 dummy_thread はこのモジュールと同じインターフェースを持ち、置き換えて使用することができます。

定数と関数は以下のように定義されています:

exception _thread.error

スレッド固有の例外です。

バージョン 3.3 で変更: 現在は組み込みの RuntimeError の別名です。

_thread.LockType

これはロックオブジェクトのタイプです。

_thread.start_new_thread(function, args[, kwargs])

新しいスレッドを開始して、そのIDを返します。スレッドは引数リスト args (タプルでなければなりません)の関数 function を実行します。オプション引数 kwargs はキーワード引数の辞書を指定します。関数が戻るとき、スレッドは静かに終了します。関数が未定義の例外でターミネートしたとき、スタックトレースが表示され、そしてスレッドが終了します (しかし他のスレッドは走り続けます)。

_thread.interrupt_main()

メインスレッドで KeyboardInterrupt を送出します。サブスレッドはこの関数を使ってメインスレッドに割り込みをかけることができます。

_thread.exit()

SystemExit を送出します。それが捕えられないときは、静かにスレッドを終了させます。

_thread.allocate_lock()

新しいロックオブジェクトを返します。ロックのメソッドはこの後に記述されます。ロックは初期状態としてアンロック状態です。

_thread.get_ident()

現在のスレッドの ‘スレッドID’ を返します。非ゼロの整数です。この値は直接の意味を持っていません; 例えばスレッド特有のデータの辞書に索引をつけるためのような、マジッククッキーとして意図されています。スレッドが終了し、他のスレッドが作られたとき、スレッド ID は再利用されるかもしれません。

_thread.stack_size([size])

新しいスレッドを作るときのスレッドスタックサイズを返します。オプションの size 引数にはこれ以降に作成するスレッドのスタックサイズを指定し、0 (プラットフォームのデフォルト値または設定されたデフォルト値) か、 32,768 (32 KiB) 以上の正の整数でなければなりません。size が指定されない場合 0 が使われます。スレッドのスタックサイズの変更がサポートされていない場合、 RuntimeError を送出します。不正なスタックサイズが指定された場合、 ValueError を送出して、スタックサイズは変更されません。32 KiB は現在のインタープリタ自身のために十分であると保証された最小のスタックサイズです。いくつかのプラットフォームではスタックサイズに対して制限があることに注意してください。例えば最小のスタックサイズが 32 KiB より大きかったり、システムのメモリページサイズ の整数倍の必要があるなどです。この制限についてはプラットフォームのドキュメントを参照してください (一般的なページサイズは 4 KiB なので、プラットフォームに関する情報がない場合は 4096 の整数倍のスタックサイズを選ぶといいかもしれません)。利用可能な環境: Windows、POSIX スレッドに対応したシステム。

_thread.TIMEOUT_MAX

Lock.acquire()timeout 引数に許される最大値です。これ以上の値を timeout に指定すると OverflowError を発生させます。

バージョン 3.2 で追加.

ロックオブジェクトは次のようなメソッドを持っています:

lock.acquire(waitflag=1, timeout=-1)

オプションの引数なしで使用すると、このメソッドは他のスレッドがロックしているかどうかにかかわらずロックを獲得します。ただし、他のスレッドがすでにロックしている場合には解除されるまで待ってからロックを獲得します (同時にロックを獲得できるスレッドはひとつだけであり、これこそがロックの存在理由です)。

整数の引数 waitflag を指定すると、その値によって動作が変わります。引数が 0 のときは、待たずにすぐ獲得できる場合にだけロックを獲得します。0 以外の値を与えると、先の例と同様、ロックの状態にかかわらず獲得をおこないます。

timeout 引数に正の float 値が指定された場合、返る前に待つ最大の時間を秒数で指定します。負の timeout 引数は無制限に待つことを指定します。waitflag が 0 の時は timeout を指定することはできません。

なお、ロックを獲得できた場合は True、できなかった場合は False を返します。

バージョン 3.2 で変更: 新しい timeout 引数。

バージョン 3.2 で変更: POSIX ではロックの取得がシグナルに割り込まれるようになりました。

lock.release()

ロックを解放します。そのロックは既に獲得されたものでなければなりませんが、しかし同じスレッドによって獲得されたものである必要はありません。

lock.locked()

ロックの状態を返します: 同じスレッドによって獲得されたものなら True、違うのなら False を返します。

これらのメソッドに加えて、ロックオブジェクトは with 文を通じて以下の例のように使うこともできます:

import _thread

a_lock = _thread.allocate_lock()

with a_lock:
    print("a_lock is locked while this executes")

警告:

  • スレッドは割り込みと奇妙な相互作用をします: KeyboardInterrupt 例外は任意のスレッドによって受け取られます。 (signal モジュールが利用可能なとき、割り込みは常にメインスレッドへ行きます。)

  • sys.exit() を呼び出す、あるいは SystemExit 例外を送出することは、 _thread.exit() を呼び出すことと同じです。

  • ロックの acquire() メソッドに割り込むことはできません — KeyboardInterrupt 例外は、ロックが獲得された後に発生します。

  • メインスレッドが終了したとき、他のスレッドが生き残るかどうかは、システムに依存します。多くのシステムでは、 try ... finally 節や、オブジェクトデストラクタを実行せずに終了されます。

  • メインスレッドが終了したとき、それの通常のクリーンアップは行なわれず、 (try ... finally 節が尊重されることは除きます)、標準 I/O ファイルはフラッシュされません。