C++中怎么避免数据竞争​

这期内容当中小编将会给大家带来有关C++中怎么避免数据竞争,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

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 h2 = async([&] { sort(std::execution::par, s); });     // spawn a task to sort
   // ...
   auto h3 = 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)


上述就是小编为大家分享的C++中怎么避免数据竞争了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。