我为这个糟糕的标题道歉,只是想找个人来确认我没有疯。
我最近偶然发现了一些已经使用多年的代码,没有人抱怨。我之所以研究它,是因为我在大量修改这个代码库时遇到了这个错误:
pthread_mutex_lock.c:90: ___pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
经过一番挖掘,我发现了一个非常奇怪的(对我来说)互斥的用法。本质上:
1.两个线程从主线程派生并分离(两个线程在同一个线程中)。cpp文件,并共享全局声明的互斥体)
1.在一个似乎是第一个命中的线程中,互斥锁被解锁,然后在循环中暂停10秒锁定,根据评论“允许其他线程处理消息”。
1.可能第二个被命中的线程(首先生成,但等待接收数据)在switch语句中有一个case,该语句使用lock_guard
锁定互斥体
我相信这是一个多方面的未定义行为,但我得到了一些反对意见,说它应该改变,因为我正在努力始终如一地最小限度地重现这个确切的错误。
我假设这是为了使互斥锁首先被循环线程解锁(从解锁状态,还没有数据供lock_guard
线程处理),然后被锁定,并且将花费其大部分时间锁定,而lock_guard
偶尔尝试锁定,并且必须等待循环将其解锁,此时它可以处理其数据,lock_guard
超出作用域,锁返回给循环线程。
我认为导致我的错误的原因是;lock_guard
线程比我的修改预期的更快地获得数据,因此lock_guard
用例被触发,然后循环线程试图解锁另一个线程的互斥锁。
我正在寻找:
- 确认它是UB来声明一个互斥体,然后在不锁定它的情况下解锁它
- 如果循环线程在
lock_guard
持有互斥锁时解锁互斥锁,则确认它是UB - 确认我的假设是什么导致我的错误(我基本上已经知道前两个参考,但要确保我没有错过一些大的大脑做事情的方式,我不知道)
- 也许有一个更好的方法来做到这一点,我会假设这可以通过首先锁定循环外的互斥体来解决?
我已经搜索了代码库,我可以看到mutex只使用了4次:当它被声明,当它在lock_guard
中使用,当它被解锁,然后锁定,所以我的while我的MRE很短,我认为它基本上有它需要的一切。要演示如何使用此互斥:
#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>
std::mutex data_mtx;
void lg_thread(){
std::lock_guard<std::mutex> guard(data_mtx);
usleep(10e6);
}
int main(int argc, char const* argv[]){
std::thread t1(lg_thread);
usleep(10000);
for (int i = 0; i < 100; i++){
data_mtx.unlock();
usleep(500);
data_mtx.lock();
}
return 0;
}
1条答案
按热度按时间fumotvh31#
我正在寻找:
解锁当前未被调用线程锁定/拥有的
mutex
是 undefined behavior,是的。lock_guard
持有互斥锁时解锁互斥锁,则确认它是UB是的,是UB。见上文。
见上文。
考虑使用
std::condition_variable
来协调线程。我假设这可以通过首先锁定循环外的互斥体来解决?
是的。这样,如果
main()
先锁定mutex
,那么lock_guard
将阻塞,等待main()
解锁它,如果lock_guard
先锁定mutex
,那么main()
将阻塞,等待lock_guard
解锁它。应该是这样