我有一个多线程应用程序,创建48个线程,都需要访问一个公共属性(stl :: map)。地图将只在线程启动时写入,剩下的时间将读取地图。这看起来像是pthread_rw_lock的完美用例,并且看起来都很好。pthread_rwlock可同时拥有多少个读者?
我碰到了一个完全不相关的seg-fault并开始分析核心。使用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,当其他线程已经从它读取?看起来似乎可以同时读取的线程数量有限制。
我看了看pthread_rwlock_attr_t
函数并没有看到任何相关的。
操作系统是Linux,SUSE 11
下面是相关的代码:
{
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的建议中更新了代码,并获得了相同的结果。
你确定*没有写作者锁定以及? – 2012-08-08 14:20:47
@MarkB这是一个很好的问题!但是,这不依赖于我没有调用过的pthread_rwlockattr_getkind_np()吗?林不知道是否有线程正在等待写入,但他们不应该是因为这应该只在一开始发生。我必须检查。 – Brady 2012-08-08 14:22:23
@MarkB,如果作者正在等待,我还没有设置pthread_rwlockattr_getkind_np()会有什么影响?据我了解,如果有连续的读者,作家可能会饿死,对吧? – Brady 2012-08-08 14:27:13