多线程。我是否需要关键部分才能进行只读访问?

时间:2012-11-14 20:14:54

标签: c++ multithreading shared-memory critical-section

我有一堆线程。他们应该访问包含配置数据的单例,该数据在创建单例时初始化一次。因此在第一次访问。因此,对单身人士的进一步行动只是只读的。在这种情况下,我是否需要关键部分?

5 个答案:

答案 0 :(得分:4)

看起来因为数据是在第一次访问时 lazily 创建的,所以指针或对单例的引用是读写的。这意味着您确实需要一个关键部分。

事实上,在这种情况下保持懒惰初始化时避免关键部分的愿望是如此普遍,以至于它导致了double-checked locking antipattern的创建。

另一方面,如果您在读取之前急切地初始化单例 ,则可以避免通过常量指针/引用访问不可变对象的关键部分。

答案 1 :(得分:1)

我理解你的问题,因为你的单身人士中存在懒惰的初始化。它仅在第一次读取时初始化。

下一次连续读取是线程安全的。但是在初始化期间并发读取呢?

如果你有这样的情况:

SomeConfig& SomeConfig::getInstance()
{
   static SomeConfig instance;
   return instance;
} 

然后它取决于你的编译器。根据C ++ 03中的这个post,如果这个静态初始化是线程安全的,那么它依赖于实现。

对于C ++ 11,它是线程安全的 - 请参阅此post的答案,引用:

  

这样的变量在控件第一次通过其声明时被初始化;这样的变量在初始化完成后被认为是初始化的。 [...]如果控件在初始化变量时同时进入声明,则并发执行应等待初始化完成。

值得注意的是,对全局变量的只读访问是线程安全的。

答案 2 :(得分:0)

没有。如果您只是在完全初始化之后读取并且数据永远不会更改,那么就不会出现竞争条件。

但是,如果以任何方式写入/修改数据,则需要同步对其的访问,即在写入之前锁定数据。

答案 3 :(得分:0)

如果您只读过一些共享数据,而且从不写,则不需要同步访问。

只需在同一时间读取和写入共享数据时,您就需要进行同步。

答案 4 :(得分:0)

规范中的官方规则是数据竞争是指一个线程可以同时写入变量,而另一个线程读取或写入相同的变量。

如果您可以证明必须在任何读者可以阅读之前进行初始化,那么您不需要同步。这通常是通过在创建(或同步)线程之前初始化,或者通过使用静态存储变量来完成的,C ++ 11保证了一些同步