2013-06-03 16 views
11

私は、プロデューサ - コンシューマモデルを使用して、pthreadでマルチスレッドプログラムを作成しました。Pthread mutex:pthread_mutex_unlock()は多くの時間を消費します

Intel VTuneプロファイラを使用してプログラムをプロファイルすると、プロデューサとコンシューマがpthread_mutex_unlockに多くの時間を費やしていました。なぜこのようなことが起こったのか分かりません。スレッドはミューテックスを取得する前に長い時間待つかもしれないと思うが、ミューテックスをリリースするのは速いはずですよね?

以下のスナップショットは、インテルVTuneのものです。コンシューマがバッファから項目を取得しようとするコードと、各コード行が消費する時間を示します。

私の質問は、pthread_mutex_unlockにこのようなオーバーヘッドがある理由です。 pthread mutex自体に問題があるのですか、それとも私が使用する方法ですか? enter image description here

+0

mutexのロックを解除すると、そのmutexに多量の競合があると遅くなる可能性があります。これは、ロック解除の作業の一部がmutexで待機しているスレッドを起動させるためです。 – caf

+6

'pthread_mutex_unlock()'呼び出しを 'pthread_cond_signal()'の呼び出しの上に移動すると、結果を見るのは面白いと思います。条件変数にシグナルを送る際に、ミューテックスを保持する必要はありません(待機している場合のみ)。ミューテックスを解放しようとするスレッドがすぐにミューテックスを取得しようとするため、シグナリングスレッドはまだ保持しています。 –

+2

@MichaelBurr良い点!私はあなたの提案でテストし、プログラムは現在約40%速くなっています。 –

答えて

2

pthread_mutex_unlock()関数は、mutexが参照するmutexオブジェクトを解放します。しかし、mutexが解放される方法は、mutexのtype属性に依存します。スケジューリング方針は、pthread_mutex_unlock()が呼び出されたときにmutexが参照するmutexオブジェクトにブロックされたスレッドが存在する場合、mutexを利用できるようになります。

mutex型がPTHREAD_MUTEX_NORMALの場合、デッドロック検出は提供されません。ミューテックスを再ロックしようとすると、デッドロックが発生します。スレッドがロックされていないミューテックスのロックを解除しようとするか、ロックされていないミューテックスをロックしようとすると、未定義の動作が発生します。

mutexタイプがPTHREAD_MUTEX_ERRORCHECKの場合、エラーチェックが行われます。スレッドがすでにロックしているミューテックスを再ロックしようとすると、エラーが返されます。スレッドがロックされていないミューテックスのロックを解除しようとするか、ロックされていないミューテックスをロックしようとすると、エラーが返されます。

mutexタイプがPTHREAD_MUTEX_RECURSIVEの場合、mutexはロックカウントの概念を維持します。スレッドが最初にミューテックスを正常に取得すると、ロックカウントは1に設定されます。スレッドがこのmutexを再ロックするたびに、ロックカウントは1増加する。スレッドがミューテックスのロックを解除するたびに、ロックカウントは1だけ減分される。ロックカウントがゼロに達すると、他のスレッドが獲得するミューテックスが利用可能になります。スレッドがロックされていないミューテックスのロックを解除しようとするか、ロックされていないミューテックスをロックしようとすると、エラーが返されます。

mutex型がPTHREAD_MUTEX_DEFAULTの場合、mutexを再帰的にロックしようとすると、未定義の動作が発生します。ミューテックスが呼び出し元のスレッドによってロックされていない場合、ロックを解除しようとすると、未定義の動作が発生します。ミューテックスがロックされていない場合、ミューテックスのロックを解除しようとすると、未定義の動作になります。

通常、PTHREAD_MUTEX_RECURSIVEミューテックスを使用することをお勧めします。この場合、ミューテックスは、カウントがゼロになり、呼び出し元スレッドがこのミューテックスにロックを持たなくなったときに使用可能になるからです。

関連する問題