在消费者循环中重复使用unique_lock

10

我在Bjarne Stroustrup的《C++程序设计语言(第四版)》第119页上发现了以下代码:

queue<Message> mqueue;
condition_variable mcond;
mutex mmutex;

void consumer()
{
    while(true) {
        unique_lock<mutex> lck{mmutex};
        mcond.wait(lck);

        auto m = mqueue.front();
        mqueue.pop();
        lck.unlock();
        // process m
    }
}

此外,还有一个生产者线程将Message推到队列中,并在循环中通知等待的线程。

我的问题是:每次迭代循环时是否需要创建一个新的unique_lock?对我来说似乎是不必要的,因为在下一行mcond.wait(lck)中,在锁定前一行后,锁直接被解锁了。

从性能角度考虑,lck变量是否可以在循环开始之前初始化?


2
通常将东西保持在使用的地方附近是一个好习惯,附近指的是作用域。这通常可以使代码更易于阅读、理解,最重要的是易于维护。 - Some programmer dude
1
最有可能的是优化器会为您提升锁变量以使其脱离循环。总之,这并不重要。不要担心它,把时间花在更有生产力的事情上。 - Jesper Juhl
1
关于性能问题,不要担心。过早的优化通常不是程序开始的好方法。相反,编写简单、易于阅读、理解、修改和维护的代码。然后,如果(只有在)性能不足时,您可以进行测量和分析以找到瓶颈,并仅集中于最严重的问题。并记得记录和注释优化内容,因为这些往往会使代码变得混乱。 - Some programmer dude
1
啊,但是wait函数期望锁被锁定!如果它没有被锁定,那么你就会有未定义的行为。因此,放置锁不仅仅是关于“接近”,而是为了避免问题。 - Some programmer dude
5
从性能的角度来看,加锁和解锁互斥量的代价比创建一个“unique_lock”更高。这就像担心赤脚开车是否可以提高油耗一样,毫无必要。 - molbdnilo
显示剩余5条评论
1个回答

8

cppreference所述,std::unique_lock构造函数如下:

explicit unique_lock( mutex_type& m );

构造函数将执行以下操作:
使用m作为关联的互斥量构造unique_lock。此外,通过调用m.lock()锁定关联的互斥量。如果当前线程已经拥有互斥量(除非互斥量是递归的),则行为是未定义的。
因此,代码在每次迭代时都会锁定互斥量。将其移出循环将改变逻辑。

对象创建时的良好资源获取方式? - Kemin Zhou

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