C++ 是C++;11由于新的常量,多线程环境中的对象可能会变慢?

C++ 是C++;11由于新的常量,多线程环境中的对象可能会变慢?,c++,multithreading,c++11,thread-safety,constants,C++,Multithreading,C++11,Thread Safety,Constants,根据Herb Sutter(),在C++11中,const方法不能按位改变对象,或者如果它们有可变的数据成员,则必须执行内部同步(例如使用互斥) 假设我有一个从多个线程访问的全局对象,并且假设它有可变成员。为了便于讨论,我们假设不能修改类的源代码(它由第三方提供) 在C++98中,这些线程将使用全局互斥来同步对此对象的访问。因此,访问需要单个互斥锁/解锁 但是,在C++11中,此对象上的任何常量成员函数调用也将调用内部同步,因此,此对象上的单个常量函数调用可能需要2次锁定/解锁操作(或更多,取决

根据Herb Sutter(),在C++11中,const方法不能按位改变对象,或者如果它们有可变的数据成员,则必须执行内部同步(例如使用互斥)

假设我有一个从多个线程访问的全局对象,并且假设它有可变成员。为了便于讨论,我们假设不能修改类的源代码(它由第三方提供)

在C++98中,这些线程将使用全局互斥来同步对此对象的访问。因此,访问需要单个互斥锁/解锁

但是,在C++11中,此对象上的任何常量成员函数调用也将调用内部同步,因此,此对象上的单个常量函数调用可能需要2次锁定/解锁操作(或更多,取决于从单个线程调用的函数数量)。请注意,仍然需要全局互斥,因为const似乎对编写器没有任何作用(如果其中一个非const方法调用const方法,则可能也会减慢编写器的速度)

< >我的问题是:如果我们所有的类都必须用C++的方式(至少可以被STL使用),这不会导致过度的同步措施吗? 谢谢

编辑:一些澄清:

  • 在C++11中,除非类的const成员函数是内部同步的(或者不执行任何写入),否则不能将其与标准库一起使用

  • 虽然C++11本身不会自动添加任何同步代码,但标准库兼容类在C++98中不需要同步,但在C++11中需要同步。因此,在C++98中,您可以不为可变成员执行任何内部同步,但在C++11中,您不能

  • 在C++11中,对该对象的任何常量成员函数调用也将调用内部同步

    为什么??这种同步不仅神奇地出现在类中,而且只有在有人显式添加它时才会出现

    因此,对该对象的单个const函数调用可能需要2次锁定/解锁操作

    只有当有人向其添加了内部互斥体时,才可以使用外部互斥体。。。但你到底为什么要这么做

    请注意,仍然需要全局互斥,因为const似乎对编写器没有任何作用(如果其中一个非const方法调用const方法,则可能也会减慢编写器的速度)

    如果类有一个用于使
    const
    成员线程安全的内部互斥锁,那么它也可以用于非
    const
    成员。如果该类没有内部互斥体,则情况与C++98相同

    我想你看到的是一个不存在的问题


    Herb的“const的新含义”不是由语言或编译器强制执行的,它只是设计指南,即优秀代码的习惯用法。为了遵循该指导,您不会向每个类添加互斥体,因此
    const
    成员可以修改
    mutable
    成员,您可以避免可变成员在极少数情况下,您必须拥有可变成员,或者要求用户自行锁定(并清楚地将类记录为需要外部同步),或者添加内部同步并支付额外费用。。。但是这种情况应该很少见,所以“C++11对象因为新常量而变慢”并不是真的,因为大多数设计良好的对象都没有可变成员。

    是的,你完全正确。您应该让您的对象遵循这些准则,因此在C++11中对它们的访问可能会较慢。如果且仅当

  • 该类具有
    mutable
    成员,这些成员由
    const
    成员函数修改

  • 正在从多个线程访问该对象

  • 如果您确保其中至少有一个是不真实的,则不会有任何更改。从多个线程访问的对象数量应始终尽可能少。并且具有可变成员的类的数量应该是最小的。你说的是一组最小的对象

    即使这样。。。所需要的只是数据竞争不会被破坏。根据可变数据是什么,这可能只是一个原子访问

    我看不出这里有什么问题。很少有标准库对象具有可变成员。我不相信你能找到需要可变成员的
    basic_string
    vector
    map
    等的合理实现

    在C++11中,除非类的const成员函数是内部同步的(或者不执行任何写入),否则不能将其与标准库一起使用

    这是不正确的。你当然可以。您不能做的是尝试跨多个线程访问该类,而这种访问方式将对这些可变成员“执行任何写入”。如果您从未以这种特定方式通过C++11类跨线程访问该对象,那么您就没事了

    所以,是的,你可以使用它们。但您只能得到自己的类提供的保证。如果您以不合理的方式通过标准库类使用类(例如您的
    const
    成员函数没有
    const
    或没有正确同步),那么这是您的错,而不是库的错

    因此,在C++98中,您可以不为可变成员执行任何内部同步,但在C++11中,您不能

    这就像说你可以在罗马帝国逃脱计算机犯罪。你当然可以。那时他们没有电脑;所以他们不知道什么是电脑犯罪

    C++98/03没有“线程化”的概念。因此,该标准没有“内部同步”的概念,那么y是什么呢