次の方法で共有


同期データ構造

同時実行ランタイムには、複数のスレッドから共有データへのアクセスを同期できる複数のデータ構造が用意されています。 これらのデータ構造は、変更頻度の低い共有データがある場合に便利です。 同期オブジェクト (クリティカル セクションなど) を使用すると、他のスレッドは、共有リソースが使用可能になるまで待機します。 そのため、このようなオブジェクトを使用して頻繁に使用されるデータへのアクセスを同期すると、アプリケーションのスケーラビリティが損なわれる可能性があります。 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_lockreader_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 によって提供される動作と比較します。

コンカレンシー ランタイム
並列プログラミングを容易にするコンカレンシー ランタイムについて説明します。また、関連トピックへのリンクを示します。