【发布时间】:2019-11-15 11:54:21
【问题描述】:
这是我的第二篇文章。我的第一篇文章是作为 C 类入门课程的本科生。我希望这次我能做得更好。
我正在为我的研究开发一个随机模型,并且我正在寻找提高算法计算效率的方法。我最近被一位同事介绍了多线程,并且我已经成功地将它实现到我的一些不需要锁的算法中......
现在我正在尝试修改/线程化需要锁的算法。在我的文学/StackOverflow/google 搜索中,我学到了很多关于互斥锁类的知识。但是,我面临的问题似乎是独一无二的。就上下文而言,我能找到的最接近答案的是:
What happens when two threads ATTEMPT to lock the same resource at the exact same time?
它仍然没有直接解决我要问的问题。
我一直在尝试使用动态分配的指向互斥对象的指针数组来控制线程之间的内存访问。我的代码编译时没有警告/错误(编译 w/flags -pthread -std=c++11),并且在抛出 Segfault 的线程算法之前完美执行。在使用 lldb 进行调查后,我发现抛出的异常如下:
经过进一步调查,我发现 lldb 输出所引用的线程都在尝试对完全相同的互斥对象执行 try_lock(),因为包含该对象地址的指针数组已传递给每个线程。
我的问题,与前面提到的帖子类似:
如果多个线程(多个线程)在完全相同的时间(处理器时钟的同一冲程)在同一个互斥体上尝试 try_lock(),会发生什么情况? mutex 类的较新实现是否有针对这种看似灾难性事件的解决方法(即 shard_mutex、timed_mutex 等)?
这最近让我大吃一惊,所以任何见解都将不胜感激。非常感谢 S/O 社区的所有帮助,在这篇文章和所有其他对我作为程序员的成长非常宝贵的内容上。
代码链接:
https://github.com/tylerbalbright/StackOverflow_7_4.git
RVEdata.cpp 中的第 751 行或第 857 行发生错误。
已修复但未解决:
我能够使用互斥对象的双端队列来修复我的代码,而不是创建指向动态创建的互斥对象的指针向量。该解决方案已由其他用户在这里提出:
How can I use something like std::vector<std::mutex>?
在我的第一次(不成功)试验中,我试图创建一个指向互斥体的指针数组,如下所示:
long int N = RuntimeVector.size(); //Varying size at runtime
std::mutex *MutexPtrs;
MutexPtrs = new std::mutex[N];
然后我会将新创建的数组作为指针传递给函数,该指针会将指向数组的指针传递给新线程,如下所示:
void SomeFunction(std::mutex *PosLocks[])
{
.
..
...
SearchersPos.push_back(std::async(std::launch::async, &RVEdata::PositiveSearch, this, PosLocks));
}
使用此方法,代码不会在每次执行时都失败,但在使用 EXC_BAD_ACCESS 时,90% 的时间都会失败。有趣的是,在每次失败的执行中,当多个线程试图 try_lock 同一个互斥体时,都会引发错误的访问。它从来没有失败过,只有 1 个线程在一个单独的互斥锁上尝试 try_lock。当我在我们的 HPC 上运行相同的代码时,大约 95% 的时间都发生了故障,但是我在 gdb 中找不到像在 lldb 中那样多的信息(我对命令行 gdb 不太熟练)。
PS - 我在 macOS High Sierra 10.13.6、Apple LLVM 版本 10.0.0 (clang-1000.11.45.5) 上运行。
【问题讨论】:
-
我很确定锁定(我在这里说的是模糊的记忆)是通过操作系统作为原子操作完成的,这意味着不会有重叠。不过,如果有人能纠正我,我会很高兴。
-
这应该可以正常工作。这就是互斥锁的意义所在。我们需要显示错误的代码来了解错误在哪里
-
重点是只有 ONE 线程会成功。为这个确切的用例明确定义了互斥锁。该实现将使用平台的适当(通常是硬件)机制来保证只有一个线程获取锁。
-
注意:BAD_ACCESS 通常是指操作系统未分配给您的应用程序的内存地址。这意味着您可能在某处有一个错误的指针。
-
一个线程会成功,另一个线程不会成功。您的段错误与此无关,是因为您的代码中存在其他错误。这不是任何类型的“灾难性事件”,根据定义,这正是互斥锁旨在处理的事情。这是他们的工作,做这种事情。
标签: c++ multithreading mutex undefined-behavior