我最近遇到了以下OpenMP死锁代码。但我无法理解这种情况。但我发现在第二个omp部分,如果我们使用locka然后lockb将没有死锁。任何人都可以帮助我理解这一点。
#pragma omp parallel shared(a, b, nthreads, locka, lockb)
#pragma omp sections nowait
{
#pragma omp section
{
omp_set_lock(&locka);
for (i=0; i<N; i++)
a[i] = ..
omp_set_lock(&lockb);
for (i=0; i<N; i++)
b[i] = .. a[i] ..
omp_unset_lock(&lockb);
omp_unset_lock(&locka);
}
#pragma omp section
{
omp_set_lock(&lockb);
for (i=0; i<N; i++)
b[i] = ...
omp_set_lock(&locka);
for (i=0; i<N; i++)
a[i] = .. b[i] ..
omp_unset_lock(&locka);
omp_unset_lock(&lockb);
}
} /* end of sections */
} /* end of parallel region */
答案 0 :(得分:1)
这很简单。如果第一个线程锁定locka
和第二个线程锁lockb
,则会发生死锁。接下来会发生什么?
第一个线程想要锁定lockb
。但是,lockb
被第二个线程锁定,因此第一个线程被阻止并等待解锁lockb
。
同样,第二个线程想要锁定locka
。但是,locka
被第一个线程锁定,因此第二个线程被阻止并等待解锁locka
。
因此,两个线程都处于阻塞状态并且都等待解锁,这种情况从未发生过,因为解锁代码位于线程被阻塞的行之下。
如果在第二个section
中,locka
被锁定,则情况会有所不同。两个线程首先尝试锁定locka
。但是,只允许一个线程成功;这是由OpenMP库保证的。因此,只有一个线程(A)锁定locka
而另一个线程(B)被阻塞,并等待locka
解锁。
线程A执行其代码,因为它没有被阻止。当它最终解锁locka
时,线程B被解锁。
在这种情况下,死锁意味着两个线程都处于阻塞状态,并等待彼此执行某些操作以解除阻塞。在第一种情况下,确实会发生这种情况,在第二种情况下,它可以发生。