专栏首页C++核心准则原文翻译C++核心准则CP.2:避免数据竞争​

C++核心准则CP.2:避免数据竞争​

CP.2: Avoid data races

CP.2:避免数据竞争

Reason(原因)

Unless you do, nothing is guaranteed to work and subtle errors will persist.

除非你做到了,否则没有任何东西可以保证动作,微妙的错误还会继续存在。

Note(注意)

In a nutshell, if two threads can access the same object concurrently (without synchronization), and at least one is a writer (performing a non-const operation), you have a data race. For further information of how to use synchronization well to eliminate data races, please consult a good book about concurrency.

简而言之,如果两个线程可以(不进行任何同步)并发访问同一个对象,至少一个线程执行写操作(执行非常量操作),就会发生数据竞争。为了获得如何更好地使用同步以消除数据竞争的进一步信息,请查阅有关并发的经典书籍。

Example, bad(反面示例)

There are many examples of data races that exist, some of which are running in production software at this very moment. One very simple example:

有关数据竞争的例子非常多,有些就发生于正在运行的产品级软件。下面是很简单的例子:

int get_id()
{
  static int id = 1;
  return id++;
}

The increment here is an example of a data race. This can go wrong in many ways, including:

代码中的增量操作就是数据竞争的例子。出错的方式可以有很多种,包括:

  • Thread A loads the value of id, the OS context switches A out for some period, during which other threads create hundreds of IDs. Thread A is then allowed to run again, and id is written back to that location as A's read of id plus one.
  • 线程A获取id的值之后操作系统上下文从A中退出一段时间,这时另外的线程生成了几百个ID。接着线程A继续运行,这时id重新被写入,而值是A读取的局部变量加1之后的结果。
  • Thread A and B load id and increment it simultaneously. They both get the same ID.
  • 线程A和B同时获取id并加1。它们得到同样的ID。

Local static variables are a common source of data races.

局部静态变量是数据竞争的常见来源。

Example, bad(反面示例):

void f(fstream&  fs, regex pattern)
{
    array<double, max> buf;
    int sz = read_vec(fs, buf, max);            // read from fs into buf
    gsl::span<double> s {buf};
    // ...
    auto h1 = async([&] { sort(std::execution::par, s); });     // spawn a task to sort
    // ...
    auto h2 = async([&] { return find_all(buf, sz, pattern); });   // spawn a task to find matches
    // ...
}

Here, we have a (nasty) data race on the elements of buf (sort will both read and write). All data races are nasty. Here, we managed to get a data race on data on the stack. Not all data races are as easy to spot as this one.

这里,保存在buf中的元素会发生(严重的)数据竞争(排序既包含读操作也包含写操作)。没有哪个数据竞争是不严重的。代码中的数据竞争发生在堆栈中的数据。不是所有的数据竞争都像本例这样容易被发现。

Example, bad(反面示例):

// code not controlled by a lock

unsigned val;

if (val < 5) {
    // ... other thread can change val here ...
    switch (val) {
    case 0: // ...
    case 1: // ...
    case 2: // ...
    case 3: // ...
    case 4: // ...
    }
}

Now, a compiler that does not know that val can change will most likely implement that switch using a jump table with five entries. Then, a val outside the [0..4] range will cause a jump to an address that could be anywhere in the program, and execution would proceed there. Really, "all bets are off" if you get a data race. Actually, it can be worse still: by looking at the generated code you may be able to determine where the stray jump will go for a given value; this can be a security risk.

现在,编译器不知道val会被修改,因此编译结果很可能是一个带有五个分支的跳转表。那么一旦val的值超越了范围[0..4],就有可能调转到程序的任何位置并从那里继续执行。真的,一旦发生了数据竞争,结果会怎么样谁也不知道。实际上,还有可能更坏:通过检查生成的代码,你或许可以准确算出针对一个给定的值,程序可以跳转到什么位置。这可能成为一个安全风险。

Enforcement(实施建议)

Some is possible, do at least something. There are commercial and open-source tools that try to address this problem, but be aware that solutions have costs and blind spots. Static tools often have many false positives and run-time tools often have a significant cost. We hope for better tools. Using multiple tools can catch more problems than a single one.

有一些是可能的,至少做点什么。有些商用和开源工具试图定位这些问题,但是需要注意的是:解决方案需要成本并存在盲区。静态工具会产生很多误报,而运行时工具通常需要巨大的成本。我们希望出现更好的工具。使用多种工具会比单一工具捕捉更多的错误。

There are other ways you can mitigate the chance of data races:

存在另外的方法可以降低数据竞争的可能性:

  • Avoid global data
  • 避免全局数据
  • Avoid static variables
  • 避免静态数据
  • More use of value types on the stack (and don't pass pointers around too much)
  • 在堆栈上更多地使用值类型(并且不要来回传递指针)
  • More use of immutable data (literals, constexpr, and const)
  • 更多地使用不可修改的数据(literals, constexpr, and const)

原文链接

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#cp2-avoid-data-races

本文分享自微信公众号 - 面向对象思考(OOThinkingDalian),作者:面向对象思考

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++核心准则边译边学-摘要

    This document is a set of guidelines for using C++ well. The aim of this documen...

    面向对象思考
  • C++核心准则Per.7:设计要为优化做准备

    Because we often need to optimize the initial design. Because a design that igno...

    面向对象思考
  • C++核心准则C.10:具体类型要好于类继承

    C.10: Prefer concrete types over class hierarchies

    面向对象思考
  • 【论文推荐】最新六篇机器翻译相关论文—跨语言推理、单语数据、可扩展工具包、不确定性、合成

    【导读】专知内容组整理了最近六篇机器翻译(Machine Translation)相关文章,为大家进行介绍,欢迎查看! 1. Baselines and tes...

    WZEARW
  • 银行业的大数据:银行如何从客户数据中获得更大的价值?

    36大数据专稿,原文作者:Vaishnavi Agrawal 本文由36大数据翻译组-欧显东翻译。

    华章科技
  • 2017年大数据的十大发展趋势

    研究人员称,会有越来越多的公司加速采用大数据技术。互联网数据中心(IDC)预测,到2020年大数据和分析技术市场,将从今年的1301亿美元增加至2030亿美元。...

    华章科技
  • 原文|21世纪地理大数据

    By Jeff de La Beaujardière 25 November 2019

    气象学家
  • 传感器数据和城市:城市可视化和健康数据的聚合(CS HC)

    移动传感器技术的发展使市议会有可能了解人们在城市空间中的行为,这有助于减轻城市周围的压力。我们提出了一种定量方法来传达对城市场所的集体意识。这些数据是在高粒度级...

    用户7495559
  • 数据仓库,就不是数据库了吗?

    A database is a collection of related data which represents some elements of the...

    Lenis
  • 大数据企业想要成为行业巨头的5个要素

    Navin Chaddha是早期阶段风险投资公司Mayfield的总经理。这家公司目前正在投资的一些公司包括Gigya、Elastica、Lyft、MapR和P...

    小莹莹

扫码关注云+社区

领取腾讯云代金券