C ++:库函数用PAUSE产生自旋锁,没有等待?

时间:2017-12-03 22:11:39

标签: c++ multithreading mutex

我需要一个自旋锁来保护资源。锁定每秒获取几次,并且在获得时保持约100条指令。换句话说,它几乎总是可用的。唯一的例外是,每隔几天,锁定将保持10毫秒。我觉得有必要将PAUSE指令或等效指令放入循环中,以确保如果超线程在此期间等待,则10毫秒不会出现气球。我想尽可能使用库函数,但我想确保函数永远不会进入等待状态,而是保持在循环中等待锁定。

我已经阅读了C ++标准版,而timed_mutex似乎可能会按我的意愿行事,但我不能保证try_lock_for()将会(1)永远不会进入睡眠状态(2)插入PAUSE。这可能是一个实施问题。

你是否知道这些实现足以建议一个可以做我想做的互斥或锁定类?

1 个答案:

答案 0 :(得分:1)

我的第一条建议是确保在走这条道路之前确实需要你认为需要的东西。想要自旋锁的主要原因是在人们知道争用非常少并且不需要完全互斥的保证(例如某种程度的公平性)的情况下,总是减少锁定的开销。您的描述符合缺乏争用的要求,但如果只是每秒获取几次锁定,那么看起来互斥锁的开销并不重要。

但如果你确定这是必要的......

通常,如果您需要像PAUSE指令那样具体的内容,并且强烈保证线程不会直接调用导致重量较大睡眠的内容,那么使用C ++标准库函数是非启动性的。你根本不会在平台上获得这样的保证。然而,要求已经有点不明确。例如。无论如何,线程很可能在旋转循环内被抢占。如果这是一个问题,那么你就进入了实时原语的领域。实时操作系统通常会提供控制级别和可移植原语来执行此类操作。

所以说,你有两条路可走。首先,您可以实现自己的螺旋锁。使用std::atomic_flag并不是特别难。为了获得PAUSE功能,半便携式,你需要使用条件编译,如下所示:     Cross-platform implementation of the x86 pause instruction。 (您可以使用x86内在函数支持和_mm_pause()而不是asm语句。)

另一种方法是使用另一个已经实现的库。 Boost的详细信息支持用于提供便携式yield功能,该功能在x86上执行PAUSE以及在其他平台上执行其他操作,但我不确定它是否仍然可用,因为合理化了很多C ++ 11的线程支持。英特尔的TBB有spin_mutex可能满足需求。 (您可能需要查看实施内容以确定。)可能还有一些较轻的重量较轻的替代品。选择预先存在的库通常取决于您的应用程序约束。

如果您正在分析性能等,即使您最终在最终代码中没有使用它,在一个平台上实现自己的性能通常也很有效,因为它可以在内部时严格控制内部做性能实验。旋转锁足够小,即使使用PAUSE等也不会花费大量时间来编写简单的旋转锁。

编辑:根据平台,pthread_spin_lock也可能符合要求。