您已经说过,它是UB。 UB表示它可以工作。或不。或在工作和使计算机自己唱摇篮曲之间随机切换。 (另请参见“鼻恶魔”。)
只有以下几种方法可以使您使用x86-64上的GCC在Fedora 31上破坏您的程序:
- 使用
-fsanitize=thread
进行编译。现在它每次都会崩溃,因为UB,它仍然是有效的C ++实现。
- 运行海尔格(
valgrind --tool=helgrind ./a.out
)。每次都会崩溃-因为UB,它仍然是托管C ++程序的有效方法。
- 目标系统上的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_semaphore
,std::counting_semaphore
。参见cppreference。
在此之前,您必须使用特定于平台的信号灯。或者,可以将自己的物品放在拥有的物品上。
本文链接:https://www.f2er.com/2252119.html