共通の属性(stl :: map)にアクセスする必要がある48個のスレッドを作成するマルチスレッドアプリケーションがあります。マップはスレッドの開始時にのみ書き込まれ、残りの時間はマップが読み取られます。これはpthread_rw_lockの完璧なユースケースのようであり、すべてがうまく機能しているように見えます。
私は完全に無関係なセグメンテーション違反に遭遇し、コアの分析を開始しました。gdbを使用してコマンドを実行したinfo threads
ところ、結果に非常に驚いていました。いくつかのスレッドが実際にマップから期待どおりに読み取られていることを確認しましたが、奇妙な部分は、rw_lockを待機しているpthread_rwlock_rdlock()でいくつかのスレッドがブロックされたことです。
ロックを待機しているスレッドのスタックトレースは次のとおりです。
#0 0xffffe430 in __kernel_vsyscall ()
#1 0xf76fe159 in __lll_lock_wait () from /lib/libpthread.so.0
#2 0xf76fab5d in pthread_rwlock_rdlock () from /lib/libpthread.so.0
#3 0x0804a81a in DiameterServiceSingleton::getDiameterService(void*) ()
スレッドが非常に多いため、読み取り中のスレッドの数とブロックされたスレッドの数を判断するのは困難ですが、他のスレッドがすでに読み取りを行っていることを考えると、読み取りを待機しているスレッドがブロックされる理由がわかりません。
だからここに私の質問があります:他のスレッドがすでにrw_lockから読み取っているのに、なぜいくつかのスレッドがrw_lockの読み取りを待ってブロックされているのですか?同時に読み取ることができるスレッドの数には制限があるように見えます。
pthread_rwlock_attr_t
関数を調べましたが、関連するものは何もありませんでした。
OSはLinux、SUSE11です。
関連するコードは次のとおりです。
{
pthread_rwlock_init(&serviceMapRwLock_, NULL);
}
// This method is called for each request processed by the threads
Service *ServiceSingleton::getService(void *serviceId)
{
pthread_rwlock_rdlock(&serviceMapRwLock_);
ServiceMapType::const_iterator iter = serviceMap_.find(serviceId);
bool notFound(iter == serviceMap_.end());
pthread_rwlock_unlock(&serviceMapRwLock_);
if(notFound)
{
return NULL;
}
return iter->second;
}
// This method is only called when the app is starting
void ServiceSingleton::addService(void *serviceId, Service *service)
{
pthread_rwlock_wrlock(&serviceMapRwLock_);
serviceMap_[serviceId] = service;
pthread_rwlock_unlock(&serviceMapRwLock_);
}
アップデート:
MarkBのコメントで述べたように、ライターを優先するようにpthread_rwlockattr_getkind_np()を設定し、待機中のライターがブロックされている場合、観察された動作は理にかなっています。しかし、私が信じているデフォルト値を使用しているのは、読者を優先することです。書き込みを待機しているスレッドがブロックされていないことを確認しました。また、コメントで@Shahbazによって提案されたようにコードを更新し、同じ結果を取得します。