16.3. thread --- マルチスレッドのコントロール

注釈

Python 3 では thread モジュールは _thread に改名されました。 2to3 ツールは、 3 コードへの変換時に、自動的に import 宣言を適合させます。しかしながら、上位の threading モジュールを使うことを検討して下さい。

このモジュールはマルチスレッド (別名 軽量プロセス (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

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

thread.LockType

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

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

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

thread.interrupt_main()

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

バージョン 2.3 で追加.

thread.exit()

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

thread.allocate_lock()

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

thread.get_ident()

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

thread.stack_size([size])

新しいスレッドが作られる際に使われるスレッドのスタックサイズを返します。オプションの size 引数は次に作られるスレッドに対するスタックサイズを指定するものですが、 0 (プラットフォームまたは設定されたデフォルト) または少なくとも 32,768 (32kB) であるような正の整数でなければなりません。 size に指定がなければ 0 が使われます。もしスタックサイズの変更がサポートされていなければ ThreadError が送出されます。また指定されたスタックサイズが条件を満たしていなければ ValueError が送出されスタックサイズは変更されないままになります。 32kB は今のところインタプリタ自体に十分なスタックスペースを保証するための値としてサポートされる最小のスタックサイズです。プラットフォームによってはスタックサイズの値に固有の制限が課されることもあります。たとえば 32kB より大きな最小スタックサイズを要求されたり、システムメモリサイズの倍数の割り当てを要求されるなどです - より詳しい情報はプラットフォームごとの文書で確認してください (4kB ページは一般的ですので、情報が見当たらないときには 4096 の倍数を指定しておくといいかもしれません)。利用可能: Windows, POSIX スレッドのあるシステム。

バージョン 2.5 で追加.

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

lock.acquire([waitflag])

オプションの引数なしで使用すると、このメソッドは他のスレッドがロックしているかどうかにかかわらずロックを獲得します。ただし、他のスレッドがすでにロックしている場合には解除されるまで待ってからロックを獲得します (同時にロックを獲得できるスレッドはひとつだけであり、これこそがロックの存在理由です)。整数の引数 waitflag を指定すると、その値によって動作が変わります。引数が 0 のときは、待たずにすぐ獲得できる場合にだけロックを獲得します。 0 以外の値を与えると、先の例と同様、ロックの状態にかかわらず獲得をおこないます。なお、ロックを獲得すると True 、できなかったときには False を返します。

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 例外は、ロックが獲得された後に発生します。

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

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