同期データ構造
同時実行ランタイムには、複数のスレッドから共有データへのアクセスを同期できる複数のデータ構造が用意されています。 これらのデータ構造は、変更頻度の低い共有データがある場合に便利です。 同期オブジェクト (クリティカル セクションなど) を使用すると、他のスレッドは、共有リソースが使用可能になるまで待機します。 そのため、このようなオブジェクトを使用して頻繁に使用されるデータへのアクセスを同期すると、アプリケーションのスケーラビリティが損なわれる可能性があります。 Parallel Patterns Library (PPL) には concurrency::combinable クラスがあります。これを使用することで、同期を行わなくても、複数のスレッドまたはタスク間でリソースを共有できます。 combinable
クラスの詳細については、「並列コンテナーと並列オブジェクト」を参照してください。
セクション
このトピックでは、次の非同期メッセージ ブロックの種類について詳しく説明します。
critical_section
concurrency::critical_section クラスは、他のタスクよりも優先させるのではなく、他のタスクを優先させる協調的な相互排他オブジェクトを表します。 クリティカル セクションは、複数のスレッドが共有データへの排他的な読み取りおよび書き込みアクセスを必要とする場合に便利です。
critical_section
クラスは再入不可能です。 concurrency::critical_section::lock メソッドは、既にロックを所有しているスレッドによって呼び出された場合、concurrency::improper_lock 型の例外をスローします。
メソッドと機能
次の表に、critical_section
クラスで定義されている重要なメソッドを示します。
メソッド | 説明 |
---|---|
lock | クリティカル セクションを取得します。 呼び出し元のコンテキストは、ロックを取得するまでブロックされます。 |
try_lock | クリティカル セクションの取得を試みますが、ブロックは行いません。 |
unlock | クリティカル セクションをリリースします。 |
[トップ]
reader_writer_lock
concurrency::reader_writer_lock クラスは、共有データに対するスレッド セーフな読み取り/書き込み操作を提供します。 複数のスレッドで共有リソースへの同時読み取りアクセスが必要だが、その共有リソースへの書き込み頻度は少ない場合、読み取り/書き込みロックを使用します。 このクラスは常に、オブジェクトに対するスレッド書き込みアクセス権を 1 つのみ付与します。
critical_section
オブジェクトは共有リソースへの排他的アクセスを取得し、それによって同時読み取りアクセスが回避されるため、reader_writer_lock
クラスのほうが critical_section
クラスよりうまく機能します。
critical_section
クラスと同様に、reader_writer_lock
クラスは、他のタスクよりも優先させるのではなく、他のタスクを優先させる協調的な相互排他オブジェクトを表します。
共有リソースに書き込む必要があるスレッドが読み取り/書き込みロックを取得すると、そのリソースにアクセスする必要がある他のスレッドは、ライターによってロックが解放されるまで、ブロックされます。 reader_writer_lock
クラスは書き込み優先ロックの一例であり、待機中のリーダーのブロックを解除する前に待機中のライターのブロックを解除するロックです。
critical_section
クラスと同様に、reader_writer_lock
クラスは再入不可能です。 concurrency::reader_writer_lock::lock メソッドと concurrency::reader_writer_lock::lock_read メソッドは、既にロックを所有しているスレッドによって呼び出された場合、improper_lock
型の例外をスローします。
Note
reader_writer_lock
クラスは再入不可能であるため、読み取り専用ロックを読み取り/書き込みロックにアップグレードしたり、読み取り/書き込みロックを読み取り専用ロックにのみダウングレードしたりすることはできません。 これらの操作のいずれかを実行すると、指定されていない動作が発生します。
メソッドと機能
次の表に、reader_writer_lock
クラスで定義されている重要なメソッドを示します。
メソッド | 説明 |
---|---|
lock | ロックへの読み取り/書き込みアクセスを取得します。 |
try_lock | ロックへの読み取り/書き込みアクセスの取得を試みますが、ブロックは行いません。 |
lock_read | ロックへの読み取り専用アクセスを取得します。 |
try_lock_read | ロックへの書き込みアクセスの取得を試みますが、ブロックは行いません。 |
unlock | ロックを解放します。 |
[トップ]
scoped_lock and scoped_lock_read
critical_section
クラスと reader_writer_lock
クラスは、相互排他オブジェクトの操作方法を簡略化する、入れ子になったヘルパー クラスを提供します。 これらのヘルパー クラスはスコープ ロックと呼ばれます。
critical_section
クラスには、concurrency::critical_section::scoped_lock クラスが含まれています。 コンストラクターは、提供された critical_section
オブジェクトへのアクセスを取得し、デストラクターはそのオブジェクトへのアクセスを解放します。 reader_writer_lock
クラスには concurrency::reader_writer_lock::scoped_lock クラスが含まれており、これは critical_section::scoped_lock
と似ていますが、指定された reader_writer_lock
オブジェクトへの書き込みアクセスを管理する点が異なります。 reader_writer_lock
クラスには、concurrency::reader_writer_lock::scoped_lock_read クラスも含まれています。 このクラスは、指定された reader_writer_lock
オブジェクトへの読み取りアクセスを管理します。
スコープ付きロックには、critical_section
オブジェクトと reader_writer_lock
オブジェクトを手動で操作する場合に、いくつかの利点があります。 通常は、スタックにスコープ付きロックを割り当てる必要があります。 相互排他オブジェクトが破棄されると、スコープ付きロックはそのオブジェクトへのアクセスを自動的に解放するため、基になるオブジェクトのロックを手動で解除する必要はありません。 これは、関数に複数の return
ステートメントが含まれる場合に便利です。 スコープ付きロックは、例外セーフなコードを記述するのにも役立ちます。 throw
ステートメントによってスタックがアンワインドされると、アクティブなスコープ ロックのデストラクターが呼び出されるため、相互排他オブジェクトは常に正しく解放されます。
Note
critical_section::scoped_lock
、reader_writer_lock::scoped_lock
、および reader_writer_lock::scoped_lock_read
クラスを使用する場合、基になる相互排他オブジェクトへのアクセスを手動で解放しないでください。 これを行うと、ランタイムが無効な状態になる可能性があります。
イベント
concurrency::event クラスは、状態をシグナル化または非シグナル化できる同期オブジェクトを表します。 共有データへのアクセスを保護することを目的とする、クリティカル セクションなどの同期オブジェクトとは異なり、イベントは実行フローを同期します。
event
クラスは、あるタスクが別のタスクの作業を完了した場合に便利です。 たとえば、あるタスクは、ネットワーク接続またはファイルからデータを読み取る別のタスクを通知します。
メソッドと機能
次の表に、event
クラスで定義されているいくつかの重要なメソッドを示します。
メソッド | 説明 |
---|---|
待機 | イベントがシグナル状態になるのを待機します。 |
set | イベントをシグナル状態に設定します。 |
reset | イベントを非シグナル状態に設定します。 |
wait_for_multiple | 複数のイベントがシグナル状態になるのを待機します。 |
例
event
クラスの使用方法を示す例については、「同期データ構造と Windows API の比較」を参照してください。
[トップ]
関連項目
同期データ構造と Windows API の比較
同期データ構造の動作を、Windows API によって提供される動作と比較します。
コンカレンシー ランタイム
並列プログラミングを容易にするコンカレンシー ランタイムについて説明します。また、関連トピックへのリンクを示します。