假设我们有以下代码架构:
main(){
sometype data;
#pragma omp parallel for
for(i=0; i< n; i++){
read data;
do some calculations that would be used in order to update the data;
#pragma omp critical{
update data;
}
}
}
我知道我们需要一个关键部分来更新数据,因为同时两个更新可能会导致损坏,但是如果一个线程在关键部分内部更新数据而另一个线程试图读取数据,会发生什么情况数据?
我在网上看到一些例子,在多线程系统中读取被认为是一种安全的行为,但是我不确定在上述情况下它是多么安全。如果它不安全,那么为了使其安全起见,适当的措施是什么?
提前谢谢
答案 0 :(得分:2)
当一个线程正在编写(更新)数据而其他线程正在从中读取数据时,您的示例中将出现竞争条件。您所读到的“阅读被认为是安全的”仅指同时阅读相同的数据而不进行修改。
您必须使用#pragma omp barrier
包围您的关键部分,以确保安全更新。
如果您只需要一个线程来更新所有数据,请考虑使用#pragma omp single
子句而不是#pragma omp critical
。
关键部分将由所有线程逐个执行。
答案 1 :(得分:1)
这实际上取决于您期望的一致性,您正在运行的体系结构以及您对数据进行的更新。
通常,如果更新一个线程中的某些数据,则应阻止其他线程使用或更新该数据。
在典型的现代处理器中,单个操作在读取输入和存储结果时只是原子操作。因此,如果另一个处理器在读取输入和写入结果之间更新相同的数据,则结果是不确定的。但读/写的数据(假设正确对齐)将是一致的。对齐几乎总是来自编译器的“正确”,因此该特定数据应该没有问题。但是,假设我们有一个包含10个值的数组:
10.1
10.2
10.3
10.4
10.5
10.6
10.7
10.8
10.9
11.0
我们通过向每个值添加1.0来“更新”。
11.1
11.2
11.3
11.4
----这里另一个线程“中断”并开始使用数组进行计算“
10.5
10.6
10.7
10.8
10.9
11.0
现在,当然,计算的第一部分将使用“新”值完成,第二部分使用“旧”值。这可能不是你想要的。
您将看不到的是-1.8812121E-64的读取,因为您的代码读取的是“半更新”值或类似的值。
从许多线程读取是安全的,但是一旦任何线程开始写入,你必须确保其他线程根本不读取数据。