对包含数据竞争的程序进行推理

问题描述 投票:0回答:2

这个问题是我的上一个问题的延续,我的理解是“

A data race is a property of an execution, not of the program in the abstract
”,这意味着只要2个线程不访问共享变量(至少有一个是写访问),实际上 而不仅仅是理论上,那么程序的行为将得到很好的定义。

根据上述理解,我想讨论以下方案:

#include <iostream>
#include <thread>
#include <unistd.h>

constexpr int sleepTime = 10;

void func(int* ptr) {
    sleep(sleepTime);
    std::cout<<"going to delete ptr: "<<(uintptr_t)ptr<<"\n";
    delete ptr;
    std::cout<<"ptr has been deleted\n";
}

int main() {

    int* l_ptr = new int(5);

    std::thread t(func, l_ptr);

    t.detach();


    std::cout<<"We have passed ptr: "<<(uintptr_t)l_ptr<<" to thread for deletion. Val at ptr: "<<*l_ptr<<"\n";

    std::cin.get();

}

如果“主线程”和“子线程”恰好同时访问共享变量,则上述程序包含数据竞争。

但是,至少可以合理地说,在使用多核 CPU时,这种情况“极不可能”在现实中发生。

c++ c++14 data-race
2个回答
5
投票

两个线程上对同一对象的访问彼此不排序。这不是“同时”的问题。

该标准定义了一个关系

Happens-Before,它只与事情发生时的挂钟时间几乎没有关系。 未定义的行为并不意味着“观察到不好的事情发生”。这意味着您无法根据 C++ 规则推断您观察到的情况。


3
投票
我的理解是“数据竞争是执行的一种属性,而不是抽象的程序的属性”,这意味着只要 2 个线程不访问共享变量(至少有一个是写访问),现实而不仅仅是理论上,那么程序的行为将得到很好的定义。

您的理解是正确的。您对这种理解的
应用

不是:

如果“主线程”和“子线程”恰好同时访问共享变量,则上述程序包含数据竞争。

数据竞争并不是要访问“共享变量
同时

”。它们是在没有适当同步的情况下访问内存,因此两次访问之间不存在“发生之前”关系。 在其他线程中删除指针和在主线程中使用它之间没有这种关系。因此,这段代码存在数据竞争。该数据竞争是其执行的一个属性,并且该执行具有数据竞争,因为该执行不包含任何会“阻止”发生数据竞争的内容。它有两种访问,其中一种是写入,它们之间没有发生之前的排序。

因此,存在数据竞争。

© www.soinside.com 2019 - 2024. All rights reserved.