像std :: queue这样的c ++标准库容器是否可以保证是可重入的?

时间:2017-01-11 00:45:44

标签: c++ multithreading

我见过人们建议我应该将标准容器(例如std :: queue和std :: vector)包装在互斥锁或类似物中,如果我想使用它们的话。 我读到需要锁定多个线程访问的容器的每个单独实例,而不是每种类型或c ++标准库的任何利用。但这假设标准容器和标准库保证可重入。

这种语言有这样的保证吗?

2 个答案:

答案 0 :(得分:7)

标准说:

  

除非在本标准中明确指定,否则它是实现定义的,可以递归地重新输入标准C ++库中的函数。

然后继续指定函数必须是可重入的,如果我正确计算它,则为零。

如果要严格遵守这方面的标准,标准库的实用性突然变得非常有限。大量的库函数调用用户提供的函数。这些函数的作者,特别是如果这些函数本身作为库发布,通常不知道它们将从何处被调用。

假设例如,这是完全合理的。任何构造函数都可以从任何标准容器的emplace_back调用;如果用户希望消除任何不确定性,他必须避免在任何构造函数中调用emplace_back。任何拷贝构造函数都可以从例如vector::resizesort,因此无法管理向量或在复制构造函数中进行排序。等等,随意。

这包括调用可能合理使用标准库的任何第三方组件。

所有这些限制可能意味着标准库的很大一部分根本无法在现实世界的程序中使用。

更新:这甚至不开始考虑线程。对于多个线程,至少处理容器和算法的函数必须是可重入的。想象一下std::vector::operator[]不可重入。这意味着无法从两个不同的线程同时访问两个不同的向量!这显然不符合标准的意图。我知道这是你的主要兴趣。重申一下,不,我不认为有重新保证;不,我不认为没有这种保证是合理的。 ---结束更新。

我的结论是,这可能是一种疏忽。除非另有规定,否则该标准应强制所有标准功能必须是可重入的。

我会

  • 完全忽略任何标准函数不可重入的可能性,除非很明显该函数不能合理地重入。
  • 向标准委员会提出问题。

答案 1 :(得分:3)

[答案留待历史用途,但请参见上午的回答。对单个函数没有要求,但 是单个全局非要求]

是的,该标准保证了标准容器成员功能的重入性。

让我来定义函数的(非)-reentrancy意味着什么。当一个线程已经在该线程的调用堆栈上,即执行时,可以在线程上调用具有良好定义的行为的可重入函数。显然,只有当控制流通过函数调用临时离开可重入函数时才会发生这种情况。如果行为没有明确定义,则该函数不可重入。

(叶子函数不能说是可重入的或不可重入的,因为控制流只能通过返回留下叶函数,但这对分析并不重要。)

示例:

fac(3)

fac(4)的行为是返回6,即使fac正在运行。因此,Django_countries是可重入的。

C ++标准确实定义了标准容器的成员函数的行为。它还定义了所有限制,在此限制下可以保证这种行为。 标准容器的成员函数在重入性方面有限制。因此,任何限制重入的实现都是不符合的。