【问题标题】:how avoid freezing other threads when one thread locks a big map当一个线程锁定大地图时如何避免冻结其他线程
【发布时间】:2013-08-06 10:54:35
【问题描述】:

如何避免冻结其他试图访问被当前线程锁定的同一张地图的线程?见以下代码:

           //pseudo code
           std::map<string, CSomeClass* > gBigMap;
           void AccessMapForWriting(string aString){
                 pthread_mutex_lock(&MapLock);

                 CSomeClass* obj = gBigMap[aString];
                 if (obj){
                       gBigMap.erase(aString);

                       delete obj;
                       obj = NULL;
                 }


                 pthread_mutex_unlock(&MapLock);
           }

           void AccessMapForReading(string aString){
                 pthread_mutex_lock(&MapLock);
                 CSomeClass* obj = gBigMap[aString];

                 //below code consumes much time
                 //sometimes it even sleeps for milliseconds
                 if (obj){
                     obj->TimeConsumingOperation();
                 }

                 pthread_mutex_unlock(&MapLock);
           }

           //other threads will also call 
           //the same function -- AccessMap
           void *OtherThreadFunc(void *){
                 //call AccessMap here
           }

【问题讨论】:

  • 可以看一下pthread_mutex_trylock:linux.die.net/man/3/pthread_mutex_trylock
  • 所有线程都会调用同一个函数——AccessMap
  • 如果您只是锁定以阅读地图,则不需要锁定,尽管我怀疑我可能会遗漏一些东西。
  • @doctorlove 某些线程可能会访问地图以从中删除一些元素,但这种情况很少发生,但访问地图以进行阅读却经常发生。
  • @doctorlove 请记住,通过operator[]“阅读”地图也可能意味着写作。

标签: c++ linux multithreading stl mutex


【解决方案1】:

考虑改用读写锁pthread_rwlock_t 有一些细节here 它说

"使用普通的互斥锁,当一个线程获得互斥锁所有其他的 线程被强制阻塞,直到所有者释放该互斥体。

绝大多数线程都只是简单的情况怎么办 读取数据?如果是这种情况,那么我们不应该关心是否存在 在临界区同时有 1 个或最多 N 个读者。在 事实上,我们通常会关心独占所有权的唯一一次是 当作者需要访问代码部分时。”

【讨论】:

  • 祝你好运 - 确保你注意 juanchopanza 的评论,并且当你阅读时你正在阅读,因为 [] 将插入不存在的键/值
【解决方案2】:

您有一个std::string 作为密钥。你能把那个键分解成一个短后缀(可能只是一个字母)和一个余数吗?因为在这种情况下,您可能会将此数据结构实现为 255 个具有 255 个锁的映射。这当然意味着在大多数情况下,没有锁争用,因为后缀不同,因此锁不同。

【讨论】:

  • 恐怕不行。实际上这里的字符串是用来存储用户名的,可能有成千上万的用户在线,这意味着这张地图中可能有数千个元素。
  • @StevePeng:这实际上相当不错。您只需使用他们姓名的第一个字母来选择地图并锁定,就可以将其分解为每个地图的一百个左右的用户。所以pthread_mutex_lock(&amp;MapLock[aString[0]);CSomeClass* obj = gBigMap[aString[0]][aString];。用户 Joe 和 Fred 不会发生锁争用,因为 Joe 使用 J 锁而 Fred 使用 F 锁。
  • 感谢 MSalters,我会尝试这种方式并选择一个比使用 pthread_rwlock_t 的方法更好的方式。
猜你喜欢
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
  • 2015-12-29
  • 2021-10-28
  • 1970-01-01
  • 2016-04-16
  • 2019-09-04
  • 1970-01-01
相关资源
最近更新 更多