【问题标题】:What does the C++ standard library guarantee to avoid data races?C++ 标准库如何保证避免数据竞争?
【发布时间】:2021-12-31 12:07:02
【问题描述】:

阅读C++11 FAQ -- Threads有一段看不懂:

因此,C++11 为程序员提供了一些规则/保证来避免数据竞争:

  • C++ 标准库函数不得直接或间接访问可由当前线程以外的线程访问的对象,除非这些对象是通过函数的参数直接或间接访问的,包括 this。
  • C++ 标准库函数不得直接或间接修改可由当前线程以外的线程访问的对象,除非这些对象是通过函数的非常量参数直接或间接访问的,包括 this。
  • 当同时修改同一序列中的不同元素时,需要 C++ 标准库实现来避免数据竞争。

我知道什么是数据竞赛和多线程,但我不明白这些句子在说什么。

你能更清楚地解释一下吗?也许举个例子?我(即应用程序程序员)在多线程上下文中做什么是安全的还是不安全的?

如果我没有读过这些,我会猜到让多个线程调用任何类型的对象的非常量方法是不安全的,但我想这是在说什么?

【问题讨论】:

  • 这些并没有说明对开发人员来说什么是安全的或不安全的。它是关于标准库 将做什么和不做什么的声明。这实际上是两个问题——首先,这三个语句的含义是什么,其次,作为开发人员,您可以做些什么来保持您的应用程序线程安全。对于后者,请参阅How to make an application thread safe?
  • re (3) std::vector<bool> 打破这个?找到了"... 保证同一个容器中的不同元素可以被不同线程同时修改...." en.cppreference.com/w/cpp/container/vector_bool
  • 这是关于内部结构的,请务必阅读用户文档以了解您使用的代码。代码只有在明确声明它是线程安全的时候才是线程安全的,即使这样你也必须正确使用它(例如 std::unique_ptr、stackoverflow.com/questions/11482580/is-unique-ptr-thread-safe/…
  • @J... 如果图书馆提供规则/保证,那不是为了让我可以安全地执行某些操作——如果是这样,那是什么?相反,也许是警告我调用一些库不保证的操作是不安全的?无论如何,我的主要问题是,“这些陈述在说什么?”。
  • @ChrisW "...可以有一个线程迭代任何标准容器的元素,而另一个线程插入新元素..." 不 - 每个线程都可以访问任何标准容器的元素容器独立。修改整个容器不是访问元素。

标签: c++ thread-safety std


【解决方案1】:

好的,我想我是从 cmets 中弄清楚的(如果我错了,请纠正我)。

  • 前两个是相似的——即一个函数只会读取或写入可通过函数参数访问的内存。

    也许这意味着,不多也不少,函数在其实现中不会读取或改变全局或静态数据。

    C 库中有一些函数违反了此规则,例如 ctime

    ctime 返回一个指向静态数据的指针,并且不是线程安全的。

  • 第三个是说一个线程可以改变容器中的一个元素,而另一个线程访问不同的元素。

    这并不意味着改变容器本质上也是安全的,例如插入一个新元素。

    vector<bool> 是这条规则的一个例外:

    std::vector<bool> 的行为类似于std::vector,但为了节省空间,它...不保证同一容器中的不同元素可以被不同线程同时修改。

【讨论】:

  • re (3) 查看我对std::vector<bool>的评论
  • 这是有道理的,这是一个例外,因为知道vector<bool> 可能每个字节有几个位。它没有实现锁是 C++ 的一个例子,它不允许一致性的小妖精干扰赤裸裸的(踏板到金属)速度/简单性。
猜你喜欢
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-15
  • 2016-09-20
相关资源
最近更新 更多