16.2. スレッド化—高レベルのスレッド化インターフェース—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/2.7/library/threading
移動先:案内検索

16.2。 糸脱毛 —高レベルのスレッドインターフェイス

ソースコード: :source: `Lib / threading.py`



このモジュールは、下位レベルの thread モジュールの上に上位レベルのスレッドインターフェイスを構築します。 mutex および Queue モジュールも参照してください。

ダミースレッドモジュールは、スレッドがないためにスレッドを使用できない状況のために提供されています。

ノート

Python 2.6以降、このモジュールは PEP 8 準拠のエイリアスとプロパティを提供し、JavaのスレッドAPIに触発されたcamelCase名を置き換えます。 この更新されたAPIは、マルチプロセッシングモジュールのAPIと互換性があります。 ただし、camelCase名の廃止のスケジュールは設定されておらず、Python2.xと3.xの両方で引き続き完全にサポートされています。


ノート

Python 2.5以降、誤って呼び出された場合、いくつかのThreadメソッドはAssertionErrorではなくRuntimeErrorを発生させます。


このモジュールは、次の関数とオブジェクトを定義します。

threading.active_count()
threading.activeCount()

現在生きているスレッドオブジェクトの数を返します。 返されるカウントは、 enumerate()によって返されるリストの長さと同じです。

バージョン2.6で変更: active_count()のスペルが追加されました。

threading.Condition()

新しい条件変数オブジェクトを返すファクトリ関数。 条件変数を使用すると、1つ以上のスレッドが別のスレッドから通知されるまで待機できます。

条件オブジェクトを参照してください。

threading.current_thread()
threading.currentThread()

呼び出し元の制御スレッドに対応する、現在の Thread オブジェクトを返します。 呼び出し元の制御スレッドが threading モジュールを介して作成されなかった場合、機能が制限されたダミースレッドオブジェクトが返されます。

バージョン2.6で変更: current_thread()のスペルが追加されました。

threading.enumerate()
現在生きているすべてのスレッドオブジェクトのリストを返します。 このリストには、デーモンスレッド、 current_thread()によって作成されたダミースレッドオブジェクト、およびメインスレッドが含まれています。 終了したスレッドとまだ開始されていないスレッドは除外されます。
threading.Event()

新しいイベントオブジェクトを返すファクトリ関数。 イベントは、 set()メソッドでtrueに設定し、clear()メソッドでfalseにリセットできるフラグを管理します。 wait()メソッドは、フラグが真になるまでブロックします。

イベントオブジェクトを参照してください。

class threading.local

スレッドローカルデータを表すクラス。 スレッドローカルデータは、値がスレッド固有のデータです。 スレッドローカルデータを管理するには、 local (またはサブクラス)のインスタンスを作成し、それに属性を格納するだけです。

mydata = threading.local()
mydata.x = 1

インスタンスの値は、スレッドごとに異なります。

詳細と広範な例については、_threading_localモジュールのドキュメント文字列を参照してください。

バージョン2.4の新機能。

threading.Lock()

新しいプリミティブロックオブジェクトを返すファクトリ関数。 スレッドがそれを取得すると、それが解放されるまで、それ以降はブロックを取得しようとします。 どのスレッドでもそれを解放できます。

ロックオブジェクトを参照してください。

threading.RLock()

新しいリエントラントロックオブジェクトを返すファクトリ関数。 再入可能ロックは、それを取得したスレッドによって解放される必要があります。 スレッドが再入可能ロックを取得すると、同じスレッドがブロックせずに再度取得できます。 スレッドは、取得するたびに1回解放する必要があります。

RLockオブジェクトを参照してください。

threading.Semaphore([value])

新しいセマフォオブジェクトを返すファクトリ関数。 セマフォは、release()呼び出しの数からacquire()呼び出しの数を引いた数に、初期値を加えたものを表すカウンターを管理します。 acquire()メソッドは、必要に応じて、カウンターを負にせずに戻ることができるまでブロックします。 指定しない場合、 value のデフォルトは1です。

セマフォオブジェクトを参照してください。

threading.BoundedSemaphore([value])
新しいバウンドセマフォオブジェクトを返すファクトリ関数。 制限付きセマフォは、現在の値が初期値を超えていないことを確認します。 含まれている場合は、ValueErrorが発生します。 ほとんどの場合、セマフォは容量が限られているリソースを保護するために使用されます。 セマフォが何度もリリースされる場合は、バグの兆候です。 指定しない場合、 value のデフォルトは1です。
class threading.Thread

制御のスレッドを表すクラス。 このクラスは、限られた方法で安全にサブクラス化できます。

スレッドオブジェクトを参照してください。

class threading.Timer

指定された間隔が経過した後に関数を実行するスレッド。

タイマーオブジェクトを参照してください。

threading.settrace(func)

threading モジュールから開始したすべてのスレッドにトレース機能を設定します。 func は、 run()メソッドが呼び出される前に、各スレッドの sys.settrace()に渡されます。

バージョン2.3の新機能。

threading.setprofile(func)

threading モジュールから開始するすべてのスレッドにプロファイル関数を設定します。 func は、 run()メソッドが呼び出される前に、各スレッドの sys.setprofile()に渡されます。

バージョン2.3の新機能。

threading.stack_size([size])

新しいスレッドを作成するときに使用されるスレッドスタックサイズを返します。 オプションの size 引数は、後で作成されるスレッドに使用されるスタックサイズを指定し、0(プラットフォームまたは構成済みのデフォルトを使用)または少なくとも32,768(32 KiB)の正の整数値である必要があります。 size が指定されていない場合、0が使用されます。 スレッドスタックサイズの変更がサポートされていない場合、 ThreadError が発生します。 指定されたスタックサイズが無効な場合、ValueErrorが発生し、スタックサイズは変更されません。 32kBは現在、インタプリタ自体に十分なスタックスペースを保証するためにサポートされている最小スタックサイズ値です。 一部のプラットフォームでは、最小スタックサイズ> 32kBが必要な場合や、システムメモリページサイズの倍数での割り当てが必要な場合など、スタックサイズの値に特定の制限がある場合があることに注意してください。詳細については、プラットフォームのドキュメントを参照してください(4kBページが一般的です)。 ;より具体的な情報がない場合は、スタックサイズに4096の倍数を使用することをお勧めします)。 可用性:Windows、POSIXスレッドを備えたシステム。

バージョン2.5の新機能。

exception threading.ThreadError
以下に説明するように、さまざまなスレッド関連のエラーに対して発生します。 多くのインターフェースは ThreadError の代わりにRuntimeErrorを使用することに注意してください。

オブジェクトの詳細なインターフェイスについては、以下で説明します。

このモジュールの設計は、Javaのスレッドモデルに大まかに基づいています。 ただし、Javaがロックと条件変数をすべてのオブジェクトの基本的な動作にする場合、それらはPythonでは個別のオブジェクトです。 Pythonの Thread クラスは、JavaのThreadクラスの動作のサブセットをサポートします。 現在、優先順位やスレッドグループはなく、スレッドを破棄、停止、一時停止、再開、または中断することはできません。 JavaのThreadクラスの静的メソッドは、実装されると、モジュールレベルの関数にマップされます。

以下で説明するすべてのメソッドは、アトミックに実行されます。

16.2.1。 スレッドオブジェクト

このクラスは、別の制御スレッドで実行されるアクティビティを表します。 アクティビティを指定するには、呼び出し可能なオブジェクトをコンストラクターに渡す方法と、サブクラスのrun()メソッドをオーバーライドする方法の2つがあります。 サブクラスでは、他のメソッド(コンストラクターを除く)をオーバーライドしないでください。 つまり、のみは、このクラスの__init__()メソッドとrun()メソッドをオーバーライドします。

スレッドオブジェクトが作成されたら、スレッドのstart()メソッドを呼び出してそのアクティビティを開始する必要があります。 これにより、別の制御スレッドでrun()メソッドが呼び出されます。

スレッドのアクティビティが開始されると、スレッドは「生きている」と見なされます。 run()メソッドが終了すると、通常どおり、または未処理の例外を発生させることにより、動作を停止します。 is_alive()メソッドは、スレッドが生きているかどうかをテストします。

他のスレッドは、スレッドのjoin()メソッドを呼び出すことができます。 これにより、join()メソッドが呼び出されたスレッドが終了するまで、呼び出し元のスレッドがブロックされます。

スレッドには名前があります。 名前はコンストラクターに渡され、name属性を介して読み取ったり変更したりできます。

スレッドは「デーモンスレッド」としてフラグを立てることができます。 このフラグの重要性は、デーモンスレッドのみが残っているときにPythonプログラム全体が終了することです。 初期値は作成スレッドから継承されます。 フラグは、daemonプロパティを介して設定できます。

ノート

デーモンスレッドは、シャットダウン時に突然停止します。 それらのリソース(開いているファイル、データベーストランザクションなど)が適切に解放されない場合があります。 スレッドを正常に停止させたい場合は、スレッドを非デーモンにし、 Event などの適切なシグナリングメカニズムを使用します。


「メインスレッド」オブジェクトがあります。 これは、Pythonプログラムの最初の制御スレッドに対応します。 デーモンスレッドではありません。

「ダミースレッドオブジェクト」が作成される可能性があります。 これらは「エイリアンスレッド」に対応するスレッドオブジェクトであり、Cコードから直接など、スレッドモジュールの外部で開始される制御スレッドです。 ダミースレッドオブジェクトの機能は制限されています。 それらは常に生きていてデーモン的であると見なされ、join()することはできません。 エイリアンスレッドの終了を検出することは不可能であるため、これらが削除されることはありません。

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})

このコンストラクターは、常にキーワード引数を使用して呼び出す必要があります。 引数は次のとおりです。

グループNoneである必要があります。 ThreadGroupクラスが実装されたときの将来の拡張のために予約されています。

target は、 run()メソッドによって呼び出される呼び出し可能なオブジェクトです。 デフォルトはNoneで、何も呼び出されないことを意味します。

name はスレッド名です。 デフォルトでは、一意の名前は「Thread- N 」の形式で構成されます。ここで、 N は小さな10進数です。

args は、ターゲット呼び出しの引数タプルです。 デフォルトは()です。

kwargs は、ターゲット呼び出しのキーワード引数の辞書です。 デフォルトは{}です。

サブクラスがコンストラクターをオーバーライドする場合、スレッドに対して他のことを行う前に、必ず基本クラスのコンストラクター(Thread.__init__())を呼び出す必要があります。

start()

スレッドのアクティビティを開始します。

スレッドオブジェクトごとに最大1回呼び出す必要があります。 これは、オブジェクトの run()メソッドが別の制御スレッドで呼び出されるように調整します。

このメソッドは、同じスレッドオブジェクトで複数回呼び出された場合、RuntimeErrorを発生させます。

run()

スレッドのアクティビティを表すメソッド。

サブクラスでこのメソッドをオーバーライドできます。 標準の run()メソッドは、オブジェクトのコンストラクターに渡された呼び出し可能オブジェクトを target 引数として呼び出し、 args からシーケンシャル引数とキーワード引数を取得します。それぞれ kwargs 引数。

join([timeout])

スレッドが終了するまで待ちます。 これにより、 join()メソッドが呼び出されたスレッドが終了するまで(通常または未処理の例外によって)、またはオプションのタイムアウトが発生するまで、呼び出し元のスレッドがブロックされます。

timeout 引数が存在し、Noneが存在しない場合は、操作のタイムアウトを秒単位(またはその端数)で指定する浮動小数点数である必要があります。 join()は常にNoneを返すため、 join()の後に isAlive()を呼び出して、タイムアウトが発生したかどうかを判断する必要があります。スレッドはまだ生きています、 join()呼び出しはタイムアウトしました。

timeout 引数が存在しないかNoneの場合、スレッドが終了するまで操作はブロックされます。

スレッドは何度も join()することができます。

join()は、現在のスレッドに参加しようとするとデッドロックが発生するため、RuntimeErrorを発生させます。 スレッドが開始される前に join()することもエラーであり、そうしようとすると同じ例外が発生します。

name

識別目的でのみ使用される文字列。 セマンティクスはありません。 複数のスレッドに同じ名前を付けることができます。 初期名はコンストラクターによって設定されます。

バージョン2.6の新機能。

getName()
setName()

name 用の2.6より前のAPI。

ident

このスレッドの「スレッド識別子」、またはスレッドが開始されていない場合はNone。 これはゼロ以外の整数です。 thread.get_ident()関数を参照してください。 スレッド識別子は、スレッドが終了して別のスレッドが作成されたときにリサイクルされる場合があります。 識別子は、スレッドが終了した後でも使用できます。

バージョン2.6の新機能。

is_alive()
isAlive()

スレッドが生きているかどうかを返します。

このメソッドは、 run()メソッドが開始する直前から run()メソッドが終了する直前まで、Trueを返します。 モジュール関数 enumerate()は、生きているすべてのスレッドのリストを返します。

バージョン2.6で変更: is_alive()のスペルが追加されました。

daemon

このスレッドがデーモンスレッドであるか(True)、そうでないか(False)を示すブール値。 これは、 start()が呼び出される前に設定する必要があります。そうしないと、RuntimeErrorが発生します。 その初期値は作成スレッドから継承されます。 メインスレッドはデーモンスレッドではないため、メインスレッドで作成されるすべてのスレッドはデフォルトでデーモン = Falseになります。

デーモン以外のスレッドが残っていない場合、Pythonプログラム全体が終了します。

バージョン2.6の新機能。

isDaemon()
setDaemon()

デーモン用の2.6より前のAPI。


16.2.2。 オブジェクトをロックする

プリミティブロックは、ロックされたときに特定のスレッドによって所有されない同期プリミティブです。 Pythonでは、これは現在利用可能な最低レベルの同期プリミティブであり、 thread 拡張モジュールによって直接実装されます。

プリミティブロックは、「ロック」または「ロック解除」の2つの状態のいずれかになります。 ロック解除状態で作成されます。 acquire()release()の2つの基本的な方法があります。 状態がロック解除されると、acquire()は状態をロックに変更し、すぐに戻ります。 状態がロックされると、acquire()は、別のスレッドでrelease()を呼び出すとロックが解除されるまでブロックされ、acquire()を呼び出すと、ロックにリセットされて戻ります。 release()メソッドは、ロックされた状態でのみ呼び出す必要があります。 状態をロック解除に変更し、すぐに戻ります。 ロック解除されたロックを解放しようとすると、 ThreadError が発生します。

状態がロック解除に変わるのを待っているacquire()で複数のスレッドがブロックされている場合、release()呼び出しが状態をロック解除にリセットすると、1つのスレッドのみが進行します。 待機中のスレッドのどれが進行するかは定義されておらず、実装によって異なる場合があります。

すべてのメソッドはアトミックに実行されます。

Lock.acquire([blocking])

ロック、ブロッキング、または非ブロッキングを取得します。

blocking 引数をTrue(デフォルト)に設定して呼び出すと、ロックが解除されるまでブロックしてから、lockedに設定してTrueを返します。

blocking 引数をFalseに設定して呼び出す場合は、ブロックしないでください。 blockingTrueに設定されている呼び出しがブロックされる場合は、すぐにFalseを返します。 それ以外の場合は、ロックをロックに設定し、Trueを返します。

Lock.release()

ロックを解除します。

ロックがロックされたら、ロック解除にリセットしてから戻ります。 ロックがロック解除されるのを待って他のスレッドがブロックされている場合は、そのうちの1つだけを続行させます。

ロック解除されたロックで呼び出されると、 ThreadError が発生します。

戻り値はありません。

locked()
Return true if the lock is acquired.


16.2.3。 RLockオブジェクト

再入可能ロックは、同じスレッドによって複数回取得される可能性のある同期プリミティブです。 内部的には、プリミティブロックで使用されるロック/ロック解除状態に加えて、「スレッドの所有」と「再帰レベル」の概念を使用します。 ロック状態では、一部のスレッドがロックを所有しています。 ロック解除状態では、スレッドはそれを所有しません。

ロックをロックするために、スレッドはそのacquire()メソッドを呼び出します。 これは、スレッドがロックを所有すると戻ります。 ロックを解除するために、スレッドはそのrelease()メソッドを呼び出します。 acquire() / release()呼び出しペアはネストできます。 最後のrelease()(最も外側のペアのrelease())のみがロックをロック解除にリセットし、acquire()でブロックされた別のスレッドを続行できるようにします。

RLock.acquire([blocking=1])

ロック、ブロッキング、または非ブロッキングを取得します。

引数なしで呼び出された場合:このスレッドがすでにロックを所有している場合は、再帰レベルを1つインクリメントして、すぐに戻ります。 それ以外の場合、別のスレッドがロックを所有している場合は、ロックがロック解除されるまでブロックします。 ロックのロックが解除されたら(どのスレッドも所有していない)、所有権を取得し、再帰レベルを1に設定して、戻ります。 ロックがロック解除されるまで待機している複数のスレッドがブロックされている場合、一度に1つだけがロックの所有権を取得できます。 この場合、戻り値はありません。

blocking 引数をtrueに設定して呼び出された場合は、引数なしで呼び出された場合と同じことを行い、trueを返します。

blocking 引数をfalseに設定して呼び出された場合、ブロックしないでください。 引数のない呼び出しがブロックされる場合は、すぐにfalseを返します。 それ以外の場合は、引数なしで呼び出されたときと同じことを行い、trueを返します。

RLock.release()

ロックを解除し、再帰レベルを下げます。 デクリメント後にゼロの場合は、ロックをロック解除にリセットし(どのスレッドも所有していない)、ロックがロック解除されるのを待って他のスレッドがブロックされている場合は、そのうちの1つだけを続行します。 デクリメント後も再帰レベルがゼロ以外の場合、ロックはロックされたままで、呼び出し元のスレッドによって所有されます。

このメソッドは、呼び出し元のスレッドがロックを所有している場合にのみ呼び出してください。 ロックが解除されたときにこのメソッドが呼び出されると、RuntimeErrorが発生します。

戻り値はありません。


16.2.4。 条件オブジェクト

条件変数は常にある種のロックに関連付けられています。 これは渡すことができます。または、デフォルトで作成されます。 (1つを渡すと、複数の条件変数が同じロックを共有する必要がある場合に役立ちます。)

条件変数には、関連するロックの対応するメソッドを呼び出すacquire()およびrelease()メソッドがあります。 wait()メソッド、notify()およびnotifyAll()メソッドもあります。 これらの3つは、呼び出し元のスレッドがロックを取得したときにのみ呼び出す必要があります。そうしないと、RuntimeErrorが発生します。

wait()メソッドはロックを解放し、別のスレッドで同じ条件変数のnotify()またはnotifyAll()呼び出しによってウェイクアップされるまでブロックします。 目覚めたら、ロックを再取得して戻ります。 タイムアウトを指定することもできます。

notify()メソッドは、条件変数を待機しているスレッドの1つをウェイクアップします(待機している場合)。 notifyAll()メソッドは、条件変数を待機しているすべてのスレッドをウェイクアップします。

注:notify()およびnotifyAll()メソッドはロックを解放しません。 これは、ウェイクアップされた1つまたは複数のスレッドがwait()呼び出しからすぐに戻るのではなく、notify()またはnotifyAll()を呼び出したスレッドが最終的にロックの所有権を放棄した場合にのみ戻ることを意味します。

ヒント:条件変数を使用する一般的なプログラミングスタイルでは、ロックを使用して、ある共有状態へのアクセスを同期します。 特定の状態変化に関心のあるスレッドは、目的の状態が表示されるまでwait()を繰り返し呼び出しますが、状態を変更するスレッドは、状態が変化するとnotify()またはnotifyAll()を呼び出します。ウェイターの1人にとって望ましい状態になる可能性があるような方法で。 たとえば、次のコードは、バッファ容量が無制限の一般的な生産者/消費者の状況です。

# Consume one item
cv.acquire()
while not an_item_is_available():
    cv.wait()
get_an_available_item()
cv.release()

# Produce one item
cv.acquire()
make_an_item_available()
cv.notify()
cv.release()

notify()notifyAll()のどちらかを選択するには、1つの状態変化が1つまたは複数の待機中のスレッドに対してのみ興味深いかどうかを検討してください。 例えば 典型的な生産者/消費者の状況では、バッファに1つのアイテムを追加するだけで、1つのコンシューマスレッドをウェイクアップする必要があります。

class threading.Condition([lock])

lock 引数が指定され、Noneではない場合、それは Lock または RLock オブジェクトである必要があり、基になるロックとして使用されます。 それ以外の場合は、新しい RLock オブジェクトが作成され、基になるロックとして使用されます。

acquire(*args)

基になるロックを取得します。 このメソッドは、基になるロックの対応するメソッドを呼び出します。 戻り値は、そのメソッドが返すものです。

release()

基になるロックを解放します。 このメソッドは、基になるロックの対応するメソッドを呼び出します。 戻り値はありません。

wait([timeout])

通知されるまで、またはタイムアウトが発生するまで待ちます。 このメソッドが呼び出されたときに呼び出し元のスレッドがロックを取得していない場合、RuntimeErrorが発生します。

このメソッドは、基になるロックを解放し、別のスレッドで同じ条件変数に対する notify()または notifyAll()呼び出しによってウェイクアップされるまで、またはオプションのタイムアウトまでブロックします。発生します。 目覚めたりタイムアウトしたりすると、ロックを再取得して戻ります。

timeout 引数が存在し、Noneが存在しない場合は、操作のタイムアウトを秒単位(またはその端数)で指定する浮動小数点数である必要があります。

基になるロックが RLock の場合、 release()メソッドを使用して解放されません。これは、再帰的に複数回取得されたときに実際にロックのロックが解除されない可能性があるためです。 代わりに、 RLock クラスの内部インターフェイスが使用されます。これにより、再帰的に何度も取得された場合でも、実際にロックが解除されます。 次に、別の内部インターフェイスを使用して、ロックが再取得されたときに再帰レベルを復元します。

notify(n=1)

デフォルトでは、この状態で待機している1つのスレッドをウェイクアップします(存在する場合)。 このメソッドが呼び出されたときに呼び出し元のスレッドがロックを取得していない場合、RuntimeErrorが発生します。

このメソッドは、条件変数を待機しているスレッドの最大 n をウェイクアップします。 待機しているスレッドがない場合は、何もしません。

現在の実装は、少なくとも n スレッドが待機している場合、正確に n スレッドをウェイクアップします。 ただし、この動作に依存することは安全ではありません。 将来、最適化された実装では、 n スレッドよりも多くのスレッドがウェイクアップする場合があります。

注:ウェイクアップされたスレッドは、ロックを再取得できるようになるまで、 wait()呼び出しから実際には戻りません。 notify()はロックを解放しないため、呼び出し元は解放する必要があります。

notify_all()
notifyAll()

この状態で待機しているすべてのスレッドをウェイクアップします。 このメソッドは notify()のように機能しますが、待機中のスレッドを1つではなくすべてウェイクアップします。 このメソッドが呼び出されたときに呼び出し元のスレッドがロックを取得していない場合、RuntimeErrorが発生します。

バージョン2.6で変更: notify_all()のスペルが追加されました。


16.2.5。 セマフォオブジェクト

これは、初期のオランダのコンピューター科学者Edsger Wによって発明された、コンピューターサイエンスの歴史の中で最も古い同期プリミティブの1つです。 ダイクストラ(彼はacquire()release()の代わりにP()V()を使用しました)。

セマフォは、acquire()呼び出しごとにデクリメントされ、release()呼び出しごとにインクリメントされる内部カウンターを管理します。 カウンターがゼロを下回ることはありません。 acquire()がゼロを検出すると、ブロックし、他のスレッドがrelease()を呼び出すまで待機します。

class threading.Semaphore([value])

オプションの引数は、内部カウンターの初期を示します。 デフォルトは1です。 指定されたが0未満の場合、ValueErrorが発生します。

acquire([blocking])

セマフォを取得します。

引数なしで呼び出された場合:入力時に内部カウンターがゼロより大きい場合は、1ずつデクリメントして、すぐに戻ります。 エントリ時にゼロの場合は、ブロックし、他のスレッドが release()を呼び出してゼロより大きくなるまで待機します。 これは適切なインターロックで行われるため、複数の accept()呼び出しがブロックされた場合、 release()はそのうちの1つだけをウェイクアップします。 実装はランダムに1つを選択する可能性があるため、ブロックされたスレッドがウェイクアップされる順序に依存しないでください。 この場合、戻り値はありません。

blocking をtrueに設定して呼び出された場合は、引数なしで呼び出された場合と同じことを行い、trueを返します。

ブロックをfalseに設定して呼び出された場合、ブロックしないでください。 引数のない呼び出しがブロックされる場合は、すぐにfalseを返します。 それ以外の場合は、引数なしで呼び出されたときと同じことを行い、trueを返します。

release()

セマフォを解放し、内部カウンタを1つインクリメントします。 エントリ時にゼロであり、別のスレッドが再びゼロより大きくなるのを待っているときに、そのスレッドをウェイクアップします。

16.2.5.1。 セマフォ例

セマフォは、データベースサーバーなど、容量が限られているリソースを保護するためによく使用されます。 リソースのサイズが固定されている状況では、制限付きセマフォを使用する必要があります。 ワーカースレッドを生成する前に、メインスレッドはセマフォを初期化します。

maxconnections = 5
...
pool_sema = BoundedSemaphore(value=maxconnections)

生成されると、ワーカースレッドは、サーバーに接続する必要があるときに、セマフォの取得メソッドと解放メソッドを呼び出します。

pool_sema.acquire()
conn = connectdb()
... use connection ...
conn.close()
pool_sema.release()

制限付きセマフォを使用すると、セマフォが取得された以上に解放される原因となるプログラミングエラーが検出されなくなる可能性が低くなります。


16.2.6。 イベントオブジェクト

これは、スレッド間の通信のための最も単純なメカニズムの1つです。1つのスレッドがイベントを通知し、他のスレッドがそれを待機します。

イベントオブジェクトは、 set()メソッドでtrueに設定し、 clear()メソッドでfalseにリセットできる内部フラグを管理します。 wait()メソッドは、フラグがtrueになるまでブロックします。

class threading.Event

内部フラグは最初はfalseです。

is_set()
isSet()

内部フラグがtrueの場合にのみ、trueを返します。

バージョン2.6で変更: is_set()のスペルが追加されました。

set()

内部フラグをtrueに設定します。 それが真になるのを待っているすべてのスレッドが目覚めます。 フラグがtrueになると wait()を呼び出すスレッドは、まったくブロックされません。

clear()

内部フラグをfalseにリセットします。 その後、 wait()を呼び出すスレッドは、 set()が呼び出されて内部フラグが再びtrueに設定されるまでブロックされます。

wait([timeout])

内部フラグが真になるまでブロックします。 エントリ時に内部フラグがtrueの場合は、すぐに戻ります。 それ以外の場合は、別のスレッドが set()を呼び出してフラグをtrueに設定するまで、またはオプションのタイムアウトが発生するまでブロックします。

Noneではなくtimeout引数が存在する場合は、操作のタイムアウトを秒単位(またはその一部)で指定する浮動小数点数である必要があります。

このメソッドは終了時に内部フラグを返すため、タイムアウトが指定されて操作がタイムアウトした場合を除いて、常にTrueを返します。

バージョン2.7で変更:以前は、メソッドは常にNoneを返していました。


16.2.7。 タイマーオブジェクト

このクラスは、一定の時間が経過した後にのみ実行する必要があるアクション、つまりタイマーを表します。 TimerThread のサブクラスであり、カスタムスレッドを作成する例としても機能します。

タイマーは、スレッドと同様に、start()メソッドを呼び出すことによって開始されます。 cancel()メソッドを呼び出すことにより、タイマーを(アクションが開始する前に)停止できます。 タイマーがアクションを実行する前に待機する間隔は、ユーザーが指定した間隔と完全に同じではない場合があります。

例えば:

def hello():
    print "hello, world"

t = Timer(30.0, hello)
t.start()  # after 30 seconds, "hello, world" will be printed
class threading.Timer(interval, function, args=[], kwargs={})
間隔秒が経過した後、引数 args とキーワード引数 kwargs関数を実行するタイマーを作成します。
cancel()
タイマーを停止し、タイマーのアクションの実行をキャンセルします。 これは、タイマーがまだ待機段階にある場合にのみ機能します。


16.2.8。 でロック、条件、およびセマフォを使用すると声明

acquire()およびrelease()メソッドを持つこのモジュールによって提供されるすべてのオブジェクトは、 with ステートメントのコンテキストマネージャーとして使用できます。 acquire()メソッドは、ブロックに入るときに呼び出され、release()は、ブロックが出るときに呼び出されます。

現在、 LockRLockConditionSemaphore 、および BoundedSemaphore オブジェクトをとして使用できます。 with ステートメントコンテキストマネージャー。 例えば:

import threading

some_rlock = threading.RLock()

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

16.2.9。 スレッドコードのインポート

インポート機構はスレッドセーフですが、スレッドセーフの提供方法には固有の制限があるため、スレッドインポートには2つの重要な制限があります。

  • まず、メインモジュール以外では、インポートによって、新しいスレッドが生成され、そのスレッドを待機するという副作用が発生することはありません。 この制限に従わないと、生成されたスレッドが直接または間接的にモジュールをインポートしようとすると、デッドロックが発生する可能性があります。
  • 次に、インタープリターがシャットダウンを開始する前に、すべてのインポートの試行を完了する必要があります。 これは、スレッドモジュールを介して作成された非デーモンスレッドからのインポートを実行するだけで最も簡単に実現できます。 デーモンスレッドおよびスレッドモジュールで直接作成されたスレッドは、システムのシャットダウンが開始された後にインポートを試行しないようにするために、他の形式の同期が必要になります。 この制限に従わないと、インタープリターのシャットダウン中に断続的な例外とクラッシュが発生します(インポートが遅れると、有効な状態ではなくなった機械にアクセスしようとするため)。