【问题标题】:Race condition: One thread creates static object, another thread uses it before it is finished initializing. How to handle?竞争条件:一个线程创建静态对象,另一个线程在完成初始化之前使用它。如何处理?
【发布时间】:2012-07-26 14:40:41
【问题描述】:

我的代码中有几个地方创建了一个函数静态对象,然后在任何时候调用该函数时使用(复制)该函数。可以从任何线程调用这些函数之一。该函数不访问除此静态对象之外的任何共享状态。

当线程1第一次调用函数时,对象被创建并初始化。但是,(幸运的是)我有一个可重复的情况,即程序切换到线程 2 并在初始化完成之前调用相同的函数。该对象被分配并使用了错误数据!

我不确定如何处理这个问题。我在初始化代码中使用了关键部分,但这甚至不是问题。这个对象在被初始化之前就被使用了。

我尝试使用 __declspec(thread) 使这个线程成为本地线程,但这显然不适用于对象。

我可以用一个关键部分来包围整个事情,这也许是最好的解决方案,但我担心代码的其他部分会出现这样的问题——如果有一个通用的解决方案会很好.

【问题讨论】:

  • 我从 MSVC 切换到 Intel 后遇到过类似的问题。我们的解决方案是在可能的情况下删除静态变量,并且在所有其他情况下确保对包含静态变量的函数的首次访问被包装在关键部分中。请注意,变量的构造函数是静态的是不够的,但对函数的访问——导致变量的初始化——必须是原子的。显然,这会导致某种代码异味,因为您必须确保对函数的每个“第一次调用”都是原子的......

标签: c++ multithreading static race-condition thread-local


【解决方案1】:

如果您使用的是 Windows,则可以使用 InitOnceExecuteOnce API。更多细节可以在thisRaymond Chen 的帖子中找到。另请查看更通用的std::call_once

【讨论】:

  • 那个东西其实是标准的,叫std::call_once
  • 感谢@bamboon 将其添加到我的答案中。
【解决方案2】:

您不能在对象上使用信号量,在创建对象时将信号量设置为 1,然后在对象初始化(并准备好使用)时将其递减为零。

不过,只需要留意资源匮乏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多