C++ 为什么sizeof(std::mutex)==40(gcc、clang、icc)?

C++ 为什么sizeof(std::mutex)==40(gcc、clang、icc)?,c++,c++11,mutex,C++,C++11,Mutex,而不是sizeof(std::atomic)==1 互斥体可以通过一个简单的std::atomic实现,因此我认为互斥体的大小可以是这么小,或者可能是4(32位)。GNU库通常使用Posix线程来实现标准线程库。它使用单个类型pthread\u mutex\u t来表示几种不同类型的互斥体;因此,它包含更复杂的互斥体所需的各种字段(例如,递归互斥体的计数器),以及指定类型的字段 原则上,在操作系统的适当支持下,std::mutex可以使用一个字节的用户内存,这是正确的。(在Linux上,它必须是

而不是
sizeof(std::atomic)==1


互斥体可以通过一个简单的
std::atomic实现,因此我认为互斥体的大小可以是这么小,或者可能是4(32位)。

GNU库通常使用Posix线程来实现标准线程库。它使用单个类型
pthread\u mutex\u t
来表示几种不同类型的互斥体;因此,它包含更复杂的互斥体所需的各种字段(例如,递归互斥体的计数器),以及指定类型的字段


原则上,在操作系统的适当支持下,
std::mutex
可以使用一个字节的用户内存,这是正确的。(在Linux上,它必须是
int
;在其他平台上,它可能是指向内核资源的整数或指针大小的句柄)。据推测,使用经过良好测试的现有实现的好处被认为超过了每个互斥体节省几十个字节的好处。

使用一个
bool
只能实现旋转锁。请注意,这将是一个不公平的锁,因为没有任何东西可以确保等待者排队,因此在最极端的情况下,在高争用率下,线程有可能永远被阻塞,因为它总是会失去获取锁的竞争

互斥实现需要操作系统的支持,才能使等待的线程进入睡眠状态。因此,互斥体需要一个标志来告诉它是否被锁定,还需要某种形式的队列描述符来让等待的线程睡眠并唤醒它们。如果您希望互斥锁能够支持递归锁定、健壮性、可选旋转、优先级反转保护等,它将需要更多的成员

互斥可以通过一个简单的
std::atomic

考虑到
mutex::lock
是一种必需的操作,而
std::atomic
很可能是一种非锁定类型,这看起来不太可能。您可以在
compare\u exchange\u strong
调用周围放置
while
循环,但这与
mutex::lock
不同,因为它会在整个等待期间浪费CPU


一般来说,
std::mutex
比定义了多线程行为的简单的
bool
复杂得多,这说明它的大小相当大,这取决于编译器:例如,.

atomic
是穷人的
mutex
。。。我的意思是,真正的穷人。我想知道为什么有些人认为这个问题不清楚或不有用。在猜测,<代码> STD::互斥体< /代码>没有实现为自旋锁。相关:(DUPE?),如下面的马克西姆所指出的。原子自旋锁不是互斥锁。它更像是一个计数为1的信号量的CPU浪费版本。但是在Linux上,通过一个原子
int
和一个系统调用,如
futex
,您可以实现一个正确的互斥体。@MikeSeymour不是真的。@MaximYegorushkin-是的,这使它“不是互斥体”。@MartinJames:它使它成为一个具有操作前提的互斥体。这并不是说它“不是一个互斥体”,它只是使它的调试比一个可以强制执行该先决条件的程序更不容易
std::mutex
本身具有相同的先决条件,如果您破坏它,则使用UB。而且使用RAII锁类型很容易在外部强制执行。@MaximYegorushkin:的确;您无法仅使用
int
实现Posix互斥。但问题不是关于POSIX互斥,而是关于代码> STD::互斥体< /C> >(就像C++库的大部分)不需要强制执行先决条件。