c++ 为什么我不应该从不同的线程解锁互斥锁
c++ Why shouldn't I unlock a mutex from a different thread
为什么我不应该从不同的线程解锁互斥锁?在 c++ 标准中,它说得很清楚:如果互斥锁当前未被调用线程锁定,则会导致未定义的行为。但据我所知,一切都在Linux(Fedora 31与GCC(上按预期工作。我认真地尝试了一切,但我无法让它表现得很奇怪。 我所要求的只是一个例子,其中某些东西,实际上是任何东西都会受到解锁来自不同线程的互斥锁的影响。
这是我写的一个快速测试,它非常错误并且不起作用,但它确实有效:
std::mutex* testEvent;
int main()
{
testEvent = new std::mutex[1000];
for(uint32_t i = 0; i < 1000; ++i) testEvent[i].lock();
std::thread threads[2000];
auto lock = [](uint32_t index) ->void { testEvent[index].lock(); assert(!testEvent[index].try_lock()); };
auto unlock = [](uint32_t index) ->void { testEvent[index].unlock(); };
for(uint32_t j = 0; j < 1000; ++j)
{
for(uint32_t i = 0; i < 1000; ++i)
{
threads[i] = std::thread(lock,i);
threads[i+1000] = std::thread(unlock,i);
}
for(uint32_t i = 0; i < 2000; ++i)
{
threads[i].join();
}
std::cout << j << std::endl;
}
delete[] testEvent;
}
正如你已经说过的,它是 UB。UB 意味着它可以工作。要不。或者在工作和让电脑唱摇篮曲之间随机切换。(另见"鼻魔"(
以下是人们可以在 Fedora 31 上使用 x86-64 上的 GCC 破坏您的程序的几种方法:
- 使用
-fsanitize=thread
编译。它现在每次都会崩溃,这仍然是一个有效的C++实现,因为 UB。 - 运行下赫尔格林德 (
valgrind --tool=helgrind ./a.out
(.它每次都会崩溃 - 仍然是托管C++程序的有效方式,因为UB。 - 目标系统上的 libstdc++/glibc/pthread 实现默认从使用"快速"互斥体切换到"错误检查"或"递归"互斥锁 (https://manpages.debian.org/jessie/glibc-doc/pthread_mutex_init.3.en.html(。请注意,这可能以与您的程序兼容的 ABI 方式实现,这意味着它甚至不必重新编译即可突然停止工作。
话虽如此,由于您使用的是C++互斥锁归结为futex实现的"快速"pthread互斥锁的平台,因此这不会偶然起作用。只是不能保证在任何时间或任何实际检查你是否在做正确事情的情况下继续工作。
>我真的想知道你为什么要这样做;)
通常你会想要类似的东西
lock();
do_critical_task();
unlock();
(在 C++ 中,锁定/解锁通常通过使用std::lock_guard
或类似功能来隐藏。
让我们假设一个线程(假设线程 A(调用了此代码并且位于关键任务内,即它也持有锁。 然后,如果从另一个线程解锁相同的互斥锁,则 A 以外的任何线程也可以同时进入关键部分。
互斥锁的主要目的是相互排斥(因此得名(,所以你要做的就是消除互斥锁的目的;)
也就是说:你应该永远相信这个标准。只有当某些东西在某个系统上工作时,并不意味着它是可移植的。另外:特别是在并发上下文中,很多事情可以解决一千次,但随后作为竞争条件的第 1001 次失败。 在数学中,你的尝试可以与"例子证明"相媲美。
- 用C++中的std::condition_variable将线程置于死锁中会有风险吗
- condition_variable、引用和线程:谁拥有锁?
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- 是否有必要获取锁并在不需要唤醒线程时通知condition_variable?
- 如果两个线程相互依赖,则 cpp 线程连接应使用连接导致死锁
- 多线程减慢程序速度:无错误共享,无互斥锁,无缓存未命中,无小工作量
- C++11:具有互斥锁的线程看到原子变量的值发生变化,尽管这是唯一可以改变它的代码
- c++ 为什么我不应该从不同的线程解锁互斥锁
- 当只有一个线程主要使用该对象而其他线程很少使用它时,如何最小化该对象的互斥锁锁定?
- 是否访问指针元组和互斥锁线程安全
- C++互斥锁线程优先级
- STD :: Mutex如何在不同的线程中解锁
- mutex::lock() 检查一次解锁状态是否已经被另一个线程锁定?
- 这个简单的(原子)锁线程安全吗
- C++线程:等待condition_variable后无法解锁阵列中的互斥锁
- 如何在 QT 中使用互斥锁线程开始轮询
- 无锁线程池
- 如何解锁锁括号内的线程
- 取消一个锁了互斥锁的线程不会解锁互斥锁
- 无法使用 pthread_kill 和 sigwait 解锁/"wake up"线程