c – pthread_rwlock可以同时读取多少个读者?

c – pthread_rwlock可以同时读取多少个读者?,第1张

概述我有一个多线程应用程序,它创建了48个线程,所有这些线程都需要访问公共属性(stl :: map).地图将仅在线程开始时写入,其余时间将从中读取地图.这似乎是pthread_rw_lock的完美用例,并且似乎都运行良好. 我碰到了一个完全不相关的seg-fault并开始分析核心.使用gdb,我执行了命令信息线程,并对结果感到非常惊讶.我观察到几个线程实际上是按照预期从地图中读取的,但奇怪的是,在p 我有一个多线程应用程序,它创建了48个线程,所有这些线程都需要访问公共属性(stl :: map).地图将仅在线程开始时写入,其余时间将从中读取地图.这似乎是pthread_rw_lock的完美用例,并且似乎都运行良好.

我碰到了一个完全不相关的seg-fault并开始分析核心.使用gdb,我执行了命令信息线程,并对结果感到非常惊讶.我观察到几个线程实际上是按照预期从地图中读取的,但奇怪的是,在pthread_rwlock_rdlock()中等待rw_lock的几个线程被阻塞了.

以下是等待锁定的线程的堆栈跟踪:

#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 threadsService *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 startingvoID ServiceSingleton::addService(voID *serviceID,Service *service){  pthread_rwlock_wrlock(&serviceMapRwLock_);    serviceMap_[serviceID] = service;  pthread_rwlock_unlock(&serviceMapRwLock_);}

更新:

正如MarkB的评论中所提到的,如果我设置了pthread_rwlockattr_getkind_np()来为编写器提供优先级,并且有一个写入器被阻塞等待,那么观察到的行为就有意义了.但是,我使用默认值,我认为是优先考虑读者.我刚刚确认没有线程被阻止等待写入.我还在评论中更新@Shahbaz建议的代码,并得到相同的结果.

解决方法 您只是观察了获取锁定所涉及的固有性能问题.这需要一些时间,你恰好在它的中间抓住那些线程.当受锁保护的 *** 作持续时间非常短时尤其如此.

Edit: Reading the source,glibc uses lll_lock to protect critical sections within its own pthread library data structures. The pthread_rwlock_rdlock checks several flags and increments counters,so it does those things while holding a lock. Once those are done,the lock is released with lll_unlock.

为了演示,我实现了一个在获取rwlock后休眠的短例程.主线程等待它们完成.但在等待之前,它会打印线程实现的并发性.

enum { CONC = 50 };pthread_rwlock_t rwlock;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIAliZER;pthread_cond_t cond = PTHREAD_COND_INITIAliZER;unsigned count;voID *routine(voID *arg){    int *fds = static_cast<int *>(arg);    pthread_rwlock_rdlock(&rwlock);    pthread_mutex_lock(&mutex);    ++count;    if (count == CONC) pthread_cond_signal(&cond);    pthread_mutex_unlock(&mutex);    sleep(5);    pthread_rwlock_unlock(&rwlock);    pthread_t self = pthread_self();    write(fds[1],&self,sizeof(self));    return 0;}

并且主线程等待计数器达到50:

int main(){    int fds[2];    pipe(fds);    pthread_rwlock_init(&rwlock,0);    pthread_mutex_lock(&mutex);    for (int i = 0; i < CONC; i++) {        pthread_t tID;        pthread_create(&tID,NulL,routine,fds);    }    while (count < CONC) pthread_cond_wait(&cond,&mutex);    pthread_mutex_unlock(&mutex);    std::cout << "count: " << count << std::endl;    for (int i = 0; i < CONC; i++) {        pthread_t tID;        read(fds[0],&tID,sizeof(tID));        pthread_join(tID,0);    }    pthread_rwlock_destroy(&rwlock);    pthread_exit(0);}

编辑:使用C 11线程支持简化示例:

enum { CONC = 1000 };std::vector<std::thread> threads;pthread_rwlock_t rwlock;std::mutex mutex;std::condition_variable cond;unsigned count;voID *routine(int self){    pthread_rwlock_rdlock(&rwlock);    { std::unique_lock<std::mutex> lk(mutex);      if (++count == CONC) cond.notify_one(); }    sleep(5);    pthread_rwlock_unlock(&rwlock);    return 0;}int main(){    pthread_rwlock_init(&rwlock,0);    { std::unique_lock<std::mutex> lk(mutex);      for (int i = 0; i < CONC; i++) {          threads.push_back(std::thread(routine,i));      }      cond.wait(lk,[](){return count == CONC;}); }    std::cout << "count: " << count << std::endl;    for (int i = 0; i < CONC; i++) {        threads[i].join();    }    pthread_rwlock_destroy(&rwlock);    pthread_exit(0);}
总结

以上是内存溢出为你收集整理的c – pthread_rwlock可以同时读取多少个读者?全部内容,希望文章能够帮你解决c – pthread_rwlock可以同时读取多少个读者?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1257023.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存