Vis*_*rma 3 c++ c++14 data-race
这个问题是我上一个问题的延续,我的理解是“ 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();
}
Run Code Online (Sandbox Code Playgroud)
上面的程序包含数据竞争,当且仅当“主线程”和“子线程”碰巧同时访问共享变量时。
然而,至少可以合理地说,在使用多核 CPU时,这种情况在现实中极不可能发生。
Cal*_*eth 10
上面的程序包含一个数据竞争,句号。
两个线程上对同一对象的访问彼此不排序。这不是“同时”的问题。
该标准定义了一个关系Happens-Before,它只与事情发生时的挂钟时间几乎没有关系。
未定义的行为并不意味着“观察到发生了不好的事情”。这意味着您无法根据 C++ 规则推断您观察到的情况。
我的理解是“数据竞争是执行的一个属性,而不是抽象的程序的属性”,这意味着只要 2 个线程不访问共享变量(至少有一个是写访问),实际上而不仅仅是理论上,那么程序的行为将得到很好的定义。
你的理解是正确的。您对这种理解的应用不是:
上面的程序包含数据竞争,当且仅当“主线程”和“子线程”碰巧同时访问共享变量时。
数据竞争不是关于“同时访问共享变量”。它们是在没有适当同步的情况下访问内存,因此两次访问之间不存在“发生之前”关系。
在其他线程中删除指针和在主线程中使用它之间不存在这种关系。因此,这段代码存在数据竞争。该数据竞争是其执行的一个属性,并且该执行具有数据竞争,因为该执行不包含任何会阻止数据竞争发生的内容。它有两种访问,其中一种是写入,它们之间没有发生之前的顺序。
因此,存在数据竞争。
条件数据竞争看起来像这样:
#include <iostream>
#include <thread>
#include <unistd.h>
#include <atomic>
std::atomic<bool> flag = false;
constexpr int sleepTime = 10;
void func(int* ptr) {
sleep(sleepTime);
std::cout<<"going to delete ptr: "<<(uintptr_t)ptr<<"\n";
delete ptr;
flag = true;
flag.notify_all();
std::cout<<"ptr has been deleted\n";
}
int main() {
int* l_ptr = new int(5);
std::thread t(func, l_ptr);
t.detach();
int i = 0;
std::cin >> i;
if(i == 5)
{
test.wait(false);
}
std::cout<<"We have passed ptr: "<<(uintptr_t)l_ptr<<" to thread for deletion. Val at ptr: "<<*l_ptr<<"\n";
std::cin.get();
}
Run Code Online (Sandbox Code Playgroud)
这将执行正确的同步,创建先发生关系,但仅当用户输入值“5”时才会执行此操作。如果他们输入其他内容,就会出现数据竞争。