# 2 `thread` -- マルチスレッドのコントロール

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

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

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

exception `error`
  スレッド特有のエラーで送出されます。

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

`start_new_thread`( | function, args[, kwargs])

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

`interrupt_main`( | )

  メインスレッドで `KeyboardInterrupt` を送出します。サブスレッドは この関数を使ってメインスレッドに割り込みをかけることができます。 バージョン 2.3 で 新たに追加 された仕様です。

`exit`( | )

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

`allocate_lock`( | )

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

`get_ident`( | )

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

`stack_size`( | [size])

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

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

`acquire`( | [waitflag])

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

`release`( | )

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

`locked`( | )

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

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

    from __future__ import with_statement
    import thread

    a_lock = thread.allocate_lock()

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

Caveats:

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

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

- I/O待ちをブロックするかもしれない全ての組込み関数が、 他のスレッドの走行を許すわけではありません。 (ほとんどの一般的なもの (`time.sleep()`, `file.read()`, `select.select()`)は期待通りに働きます。)

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

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

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