Win32並行処理プログラミング入門19
並列処理で考えねばならないのは、リソースを長時間ロックもしくは排他制御していないかという点です。ですから、サンプルのこの部分は問題があります。
//サンプルより抜粋
//並列的に実行するメソッド
void AddFunc( int count )
{
EnterCriticalSection( &number_section ); //開始地点
long tmp = this->getNumber();
for ( int i = 0; i < count; i++ ) {
++tmp;
}
this->setNumber( tmp );
LeaveCriticalSection( &number_section ); //終了地点
}
このやり方では、1つのスレッドしかAdd関数の処理を実行できない問題があります。排他制御の時間が長すぎます。その観点から、次の様なプログラムを思いつくと思います。
//排他制御の時間を少なくする
void AddFunc( int count )
{
for ( int i = 0; i < count; i++ ) {
EnterCriticalSection( &number_section ); //開始地点
this->setNumber( this->getNumber() + 1 );
LeaveCriticalSection( &number_section ); //終了地点
}
}
このプログラムは、排他制御の時間が短く、他のスレッドが共有リソースを操作するチャンスを積極的に与えています。しかし、このプログラムもオーバーヘッドが高いという問題があります。クリティカルセクションの開始と終了は、それなりのコストが必要となります。そのコストを頻繁に払うとオーバーヘッドが高くなり、逆にパフォーマンスが下がる可能性が十分にあります。
また、実際はサンプルとは違い、実装の詳細が分からない場合が多々あります。その様な状況下では、この様な実装に関する知識が要求される方法を採れないでしょう。何故ならば、実装が隠蔽されている場合、どのリソースを使っているか分からないからです。そうなると、メソッドもしくは関数そのものをクリティカルセクションで囲まないとならないかもしれません。ですが、それでは並行度が下がりますし、リソースを把握していない場合、他のメソッドも同じリソースを操作する可能性を考えると、非常に危険だと言えます。