ロックメカニズムは、再入可能ロックなしで最大の効率が得られるように考えられています。このスキーマには、2 種類の相互排他オブジェクトがあります。
独立したバッファ演算のたびに、バッファのロックとロックの解除を繰り返すのは非効率的です。たとえば、文字の char* シーケンスを挿入する場合、文字を挿入するたびにインライン basic_streambuf 関数に対する呼び出しが行われます。したがって、ロックメカニズムも高いレベルで実行されます。書式付きストリーム関数と、書式なしストリーム関数のいずれについても、監視オブジェクトコンストラクタに対してロックが設定され、監視オブジェクトデストラクタに対してロックが解除されます。関数で監視クラスを使用しない場合、ロックは関数内部に直接設定されます。basic_istream::seekg と basic_ostream::seekg の場合がそうです。
次に例を挙げます。
スレッド 1: |
スレッド 2: |
|
cout << "Hello Thread 1"
<< endl; |
cout << "Hello Thread 2"
<< endl; |
スレッド 1 でバッファを最初にロックすると、文字シーケンス "Hello Thread 1" は stdout に出力され、ロックが解除されます。スレッド 2 がロックを引き継ぎ、文字シーケンスを出力して解除します。
basic_streambuf 相互排他オブジェクトでは、ストリームの演算ごとにロックが 1 回設定されます。このスキーマは、高いパフォーマンスが得られるという点で明らかに有利ですが、バッファの機能を直接利用している間は、バッファが保護されません。これを解決するために、関数とマニピュレータが用意されています。次の例で、この機能を説明します。
スレッド 1: |
スレッド 2: |
|
cout << "Hello Thread 1"
<< endl; |
cout<< __lock; do { cout.rdbuf()->sputc(*t); } while ( *t++!=0 ) cout << __unlock; |
このスキーマでは、スレッド 2 を最初に実行すると、文 cout<< __lock; を呼び出すときに、cout.rdbuf() によって示されている basic_streambuf オブジェクトがロックされます。スレッド 1 では、ロックを解除する文 cout << __unlock; にスレッド 2 が達するまで、文字シーケンスを出力することはできません。この方法は、利用しやすく、ストリームとバッファの両方の操作で高いパフォーマンスが得られます。
1 つのスレッドにある複数のスレッドをロックして、同時に実行する複数のスレッドによって実行される操作の大域上の順序を守ることができます。次の例は、この方法を示したものです。
スレッド 1: |
スレッド 2: |
|
cout << __lock; cout << "Thread 1 begin" << endl; cout << "Thread 1 completion" << endl; cout << __unlock; |
cout << "Thread 2 begin"
<< endl; |
この例では、cout に結合している basic_streambuf オブジェクトをスレッド 1 で最初にロックすると、スレッド 1 が文 cout << __unlock; に達するまで、スレッド 2 では文字シーケンスを出力することができません。その結果、次のように出力順序が守られます。
スレッド 1 が最初にロックされる: |
スレッド 1 開始 スレッド 1 終了 スレッド 2 開始 |
|
スレッド 2 が最初にロックされる: |
スレッド 2 開始 スレッド 1 開始 スレッド 1 終了 |
Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。
OEM リリース, 1998 年 6 月