std::mutex是否公平?

4

正如问题所述,std::mutex是否公平?即,如果线程A锁定了互斥锁,然后B和C按此顺序调用'lock()',它们会以相同的顺序获得互斥锁,还是顺序不确定?

文档根本没有涉及这个问题。


6
如果文档没有涉及到这一点,我猜那就意味着它是未指定的。 - Gabe
2
为了保持它们的顺序:https://dev59.com/A1_Va4cB1Zd3GeqPW8ta - fatihk
1
这个http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf可能是“文档”的更好来源。 - doctorlove
谢谢你的提示,但这只是一份草稿。 - mort
你需要支付相当一大笔钱才能获得发布版本。公平性是实现细节。唯一可以真正依赖的是,不提供任何公平性的实现不太可能长久存活。换句话说,当你使用别人的代码时,你应该有一些信心他们做得对。如果你不指明实现,我们无法帮助你感觉更好。 - Hans Passant
我不知道... 我对标准的阅读表明它是公平的。 - John Dibling
2个回答

8

标准(§30.4)未涉及互斥锁中竞争线程之间公平性的要求,因此可能是公平的也可能是不公平的。

实际上,std::mutex 的实现通常会使用其所在平台提供的互斥锁实现,这些实现大多数都是不公平的,因为这样通常更加简单高效。例如,在 Windows 上,互斥锁通常是公平的,但并非总是如此。某些实现(e.g. Thread Building Block)提供了特殊的公平互斥锁,但这些互斥锁不是基于操作系统本地的互斥锁实现的,通常是作为自旋锁的方式实现的(其中有自己的注意事项)。


1
如果文档没有涉及到这个问题,我们可以建议将其视为未指定的。如果没有指定,你可能会惊讶地猜测他们按照相同的顺序获得锁定...... 为了确保线程按照请求的顺序获取互斥量,我建议你查看 std::condition_variablestd::condition_variable_any。它们都在 <condition_variable> 库头文件中声明。在两种情况下,它们需要与互斥量一起使用,以提供适当的同步。以下是如何使用它的一个小例子:
#include <mutex>
#include <condition_variable>

std::mutex mut;
std::queue<dummyData> data;
std::condition_variable cond;

void dummyDataPrepare()
{
    while( more_data_in_preparation() )
    {
        std::lock_guard<std::mutex> lo( mut );
        // doing many things on data
        cond.notify_one();
    }
}

void dummyDataProcessingThread()
{
    while( true )
    {
        std::unique_lock<std::mutex> lo( mut );
        cond.wait( lo,
            []{ return !data.empty(); });
        // Do whatever you want ...
        lo.unlock();
    }
}

这个例子展示了在对数据进行操作之前如何等待某些数据被处理。

我需要知道std::mutex是否公平,而不是如何创建公平锁。 - mort
1
响应在我的帖子顶部。我认为这不公平,因为没有具体说明。这就是为什么我想给你一个让锁变得公平的方法... - Pierre Fourgeaud
3
使用condition_variable如何确保公平性? - ronag
至少,通过一些代码,你可以让它变得公平。事实上,wait方法会解锁互斥锁并将线程放入等待条件的线程列表中,因此你可以创建一个公平锁。这里有一个链接,其中包含两个示例:https://dev59.com/AmUq5IYBdhLWcg3wF8rw - Pierre Fourgeaud
我认为CV并不能成为一个公平的互斥锁。CV.notify_one()可以唤醒任何线程。也许你可以使用FIFO(队列)数据结构来实现你自己的CV版本。 - Shriganesh Shintre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接