std::queue pop push 线程安全性

4
基本上我的问题是:在没有同步的情况下,从两个线程调用front+pop和push是否安全? 我已经阅读了相关内容,但从未找到清晰的答案。有些人说你应该使用互斥锁,但有些人暗示你可以为push和pop使用两个不同的互斥锁。这是真的吗? 这段代码是否具有未定义的行为?
std::queue<int> queue;

int pop()
{
    int x = queue.front();
    queue.pop();
    return x;
}

void push(int x)
{
    queue.push(x);
}

int main()
{
    queue.push(1);
    std::thread t1(pop);
    std::thread t2(push);

    t1.join();
    t2.join();
}

我认为这是未定义的行为,但是您可以设计一个安全的队列来进行弹出和推入操作,那么为什么std::queue不是这样呢?

如果非要用一个词来回答的话,那就是“开销”。 - Zeta
除非另有说明,否则所有标准函数和类都应被视为不安全。 - Some programmer dude
1个回答

10
不是的。标准容器不是线程安全的,你不能从两个线程中改变它们。你将需要使用互斥量或无锁队列。问题在于std::queue必须能够处理像std::string这样的对象,这些对象无法原子移动或构造,并且std::queue还必须支持任意大小。
大多数无锁队列仅适用于机器字大小的类型和固定的最大大小。如果您需要std::queue的灵活性和线程安全性,则必须手动使用互斥量。将互斥量添加到默认实现中也非常浪费,因为现在每个应用程序都会获得线程安全性,即使它不需要。

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