【问题标题】:Multithreading. Do I need critical sections for read-only access?多线程。我需要只读访问的关键部分吗?
【发布时间】:2012-11-03 09:47:17
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 您的链接说,在 C++11 中,延迟初始化的单例不需要锁定。
    【解决方案2】:

    我理解您的问题,因为您的单例中有延迟初始化。它仅在第一次读取时初始化。

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

    如果你有这样的情况:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      没有。如果您只是在完全初始化后读取这些数据,并且数据从不改变,那么就不可能发生竞争条件。

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

      【讨论】:

      • @DevNoob:是的,我正要编辑我的回复,因为我看到了这个:因此在第一次访问时。所以你需要保护它正在初始化。但是,如果您的程序始终使用此数据(即,您的程序无法运行(或可能性很小)并且此数据不会被初始化),那么您实际上并没有需要延迟初始化,它不会为您节省任何东西。无论哪种方式,数据都需要在写入时受到保护。之后,您可以阅读和阅读。
      【解决方案4】:

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

      您只需要在可能同时读取和写入共享数据时进行同步。

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-12
          • 1970-01-01
          • 2015-01-11
          • 1970-01-01
          • 1970-01-01
          • 2011-08-18
          • 1970-01-01
          相关资源
          最近更新 更多