c++ - 为什么没有像 pthread_mutex_t & std::mutex 那样的 std::等价于 pthread_spinlock_t?

标签 c++ linux multithreading c++11

我已经将 pthreads 用于并发程序,主要使用自旋锁、互斥锁和条件变量。

我开始研究使用 std::thread 和 std::mutex 的多线程,我注意到 pthread 中似乎没有与自旋锁等效的东西。

有谁知道这是为什么?

最佳答案

there doesn't seem to be an equivalent to spinlock in pthreads.



自旋锁在用户空间中通常被认为是错误的工具,因为在持有自旋锁时无法禁用线程抢占(与内核中不同)。这样一个线程可以获取自旋锁然后被抢占,导致所有其他尝试获取自旋锁的线程不必要地自旋(如果这些线程具有更高的优先级,可能会导致死锁(等待 I/O 的线程可能会获得优先级)唤醒时增强))。这个推理也适用于所有无锁数据结构,除非数据结构确实是 wait-free (除了 boost::spsc_queue 之外,没有多少实际有用的)。

在内核中,锁定自旋锁的线程在释放自旋锁之前不能被抢占或中断。这就是为什么自旋锁在那里是合适的(当 RCU 不能使用时)。

在 Linux 上,可以通过使用隔离的 CPU 内核和固定到这些隔离内核的 FIFO 实时线程来防止抢占(不确定是否完全,但最近内核已朝着这种理想的效果进行了更改)。但这需要经过深思熟虑的内核/机器配置以及旨在利用该配置的应用程序。尽管如此,人们确实将这样的设置用于关键业务应用程序以及用户空间中的无锁(但不是无等待)数据结构。

在 Linux 上,有自适应互斥锁 PTHREAD_MUTEX_ADAPTIVE_NP , 旋转 for a limited number of iterations在内核阻塞之前(类似于 InitializeCriticalSectionAndSpinCount )。但是,不能通过 std::mutex 使用该互斥锁。界面,因为没有自定义非可移植的选项pthread_mutexattr_t初始化前 pthread_mutex_t .

一个人无法通过 std::mutex 启用进程共享、稳健性、错误检查或优先级反转预防。界面。在实践中,人们编写自己的 pthread_mutex_t 包装器。它允许设置理想的互斥属性;以及相应的条件变量包装器。标准锁,如 std::unique_lockstd::lock_guard可以重复使用。

IMO,可以在 std:: 中设置所需的互斥锁和条件变量属性。 API,例如提供 protected派生类的构造函数将初始化该 native_handle ,但没有。那个 native_handle 做平台特定的东西看起来是个好主意,但是,派生类必须有一个构造函数才能适本地初始化它。互斥或条件变量初始化后,native_handle几乎没用。除非这个想法只能通过 native_handle到(C 语言)API 需要一个指针或对初始化的引用 pthread_mutex_t .

还有一个 Boost/C++ 标准不接受信号量的例子,因为信号量太大了,不能自挂,互斥量(本质上是一个二进制信号量)和条件变量是更基本和更灵活的同步原语,out其中一个semaphore can be built .

从 C++ 标准的角度来看,这些可能是正确的决定,因为教育用户正确使用自旋锁和信号量是一项艰巨的任务。而高级用户可以抽出一个 wrapper for pthread_spinlock_t with little effort .

关于c++ - 为什么没有像 pthread_mutex_t & std::mutex 那样的 std::等价于 pthread_spinlock_t?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61526837/

相关文章:

c++ - 将 char * 转换为 vector C++

c++ - 在 C++23 中显式 *this 对象参数提供什么?

c++ - 同时从 2 个线程读取全局变量

java - 目前在 Java 中可以实现的最低 TCP 延迟是多少?

c++ - 运算符重载以显示用户定义的数据类型

c++ - lambda 如何捕获自身以进行异步调用?

c - 如何写入命名管道而不是等待读取管道

linux - 我需要使用 Linux 几天。网上有免费服务吗?

linux - FTP 设置阻止 CD 命令

java - 如果未收到数据,请发送并重试数据?