为什么我不应该从另一个线程解锁互斥锁

为什么我不应该从其他线程解锁互斥锁?在c ++标准中,它说得很清楚:如果互斥对象当前未由调用线程锁定,则它将导致未定义的行为。但据我所知,一切都可以在Linux上正常运行(带有GCC的Fedora 31)。我认真尝试了所有内容,但无法使其表现出异常。 我只想举一个例子,说明从其他线程解锁互斥锁会影响某些事情,实际上什么都会受到影响。

这是我写的一个快速测试,它是超级错误的,应该不起作用,但是可以:

#img {
    width: 90%;
    max-width: 90%;
    height: auto; 
}
iCMS 回答:为什么我不应该从另一个线程解锁互斥锁

您已经说过,它是UB。 UB表示它可以工作。或不。或在工作和使计算机自己唱摇篮曲之间随机切换。 (另请参见“鼻恶魔”。)

只有以下几种方法可以使您使用x86-64上的GCC在Fedora 31上破坏您的程序:

  1. 使用-fsanitize=thread进行编译。现在它每次都会崩溃,因为UB,它仍然是有效的C ++实现。
  2. 运行海尔格(valgrind --tool=helgrind ./a.out)。每次都会崩溃-因为UB,它仍然是托管C ++程序的有效方法。
  3. 目标系统上的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 ++ 20具有信号灯:std::binary_semaphorestd::counting_semaphore。参见cppreference

在此之前,您必须使用特定于平台的信号灯。或者,可以将自己的物品放在拥有的物品上。

本文链接:https://www.f2er.com/2252119.html

大家都在问