Fortran OpenMP如何用锁和sleep函数替代显式同步屏障解决阻塞问题
问题原因
- 死循环根源:你设置的等待退出条件是
a==13,但第一个通过等待的非0线程(比如1号线程)退出循环后会立刻执行a=a+1,将a的值修改为14,剩下的2、3号线程后续拿到锁判断时,a的值永远不可能再等于13,就会一直卡在轮询循环中无法退出。 - 额外隐患:非0线程对共享变量a的修改操作没有加锁保护,存在并发竞争风险,可能导致a的最终计算结果不符合预期。
修复方案
仅需要将非0线程等待循环中的判断条件从a==13修改为a>=13即可,因为0号线程完成修改后a的值最小为13,后续只会递增不会降低,只要a大于等于13就说明0号线程的修改已经完成,可以退出等待。同时建议给非0线程修改a的操作也加上锁保护,避免并发问题。
修复后的核心代码片段如下:
if (num_thread .ne. 0) then do call omp_set_lock(lck) if (a >= 13) then ! 仅需把判断条件从==改成>= exit else call omp_unset_lock(lck) call system_sleep(1) end if end do call omp_unset_lock(lck) end if ! 修改a时加锁保证线程安全 if (num_thread == 1) then call omp_set_lock(lck) a=a+1 call omp_unset_lock(lck) end if !$OMP BARRIER if (num_thread == 2) then call omp_set_lock(lck) a=a+1 call omp_unset_lock(lck) end if !$OMP BARRIER if (num_thread == 3) then call omp_set_lock(lck) a=a+1 call omp_unset_lock(lck) end if
修改后程序即可正常运行,最终输出结果和原代码一致为16。
内容的提问来源于stack exchange,提问作者hakim
相关产品推荐
相关产品推荐

