只要程序不允许同时写入存储在模块中的共享数据结构的相同元素,它是否是线程安全的?我知道这是一个菜鸟问题,但无法在任何地方明确地找到它。情况如下:
在程序开始时,数据被初始化并存储在模块级可分配数组(FIELDVARS
)中,然后任何子程序都可以访问该数组,其中模块由USE
语句引用。
现在假设程序进入多线程和/或多核计算阶段,并且访问FIELDVARS
以进行"读/写"重复多次同时调用子程序(COMPUTE
)时的操作。
计算阶段完成后,程序将返回单线程阶段,FIELDVARS
必须在后续子程序(POST
)中使用。但是,FIELDVARS
无法添加到COMPUTE
或POST
的输入参数中,因为这些是从闭源主程序中调用的。因此,模块级数组用于在子例程之间传递addt< l<数据。
假设设计了FIELDVARS
和COMPUTE
,以便每次调用COMPUTE
始终可以访问一组FIELDVARS
的唯一元素,这些元素可以保证与任何其他电话不同,以便同时"写"对相同元素的操作永远不会发生。例如:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... ] <-- FIELDVARS
^---call 1---^ ^---call 2---^ ... <-- Each call to COMPUTE is guaranteed to access a specific set of elements of FIELDVARS.
问题:此方案是否被视为&#34;线程安全&#34;,&#34;有条件安全&#34;,或&#34;不是线程安全&#34;?如果它不安全,具体的危险是什么?你建议怎样处理它?</ p>
其他相关细节:
COMPUTE
,POST
和其他子程序,以及可以传入的args。这就是模块级数组用于传递的原因不同子程序之间的数据,而不是作为一个arg。
! DEMO MODULE W/ ALLOCATABLE INTEGER ARRAY
module DATA_MODULE
integer, dimension(:), allocatable :: FIELDVARS !<-- allocated/populated elsewhere, prior to calling COMPUTE
end module DATA_MODULE
! DEMO COMPUTE SUBROUTINE (THREADED PHASE W/ MULTIPLE SIMULTANEOUS CALLS)
subroutine COMPUTE(x, y, x_idx, y_idx, flag)
use DATA_MODULE
logical :: flag
integer :: x,y,x_idx,y_idx !<-- different for every call to COMPUTE
if (flag == .false.) then !<-- read data only
...
x = FIELDVARS(x_idx)
y = FIELDVARS(y_idx)
...
else if (flag == .true.) then !<-- write data
...
FIELDVARS(x_idx) = 0
FIELDVARS(y_idx) = 0
...
endif
end subroutine COMPUTE
答案 0 :(得分:3)
很好,很多程序都依赖于这个事实。在OpenMP中,您经常循环遍历数组,不同的线程可以轻松地处理内存中彼此接近的元素,尤其是在分配给每个线程的块的边界上。
在现代CPU中,这不是问题。另请参阅https://en.wikipedia.org/wiki/Cache_coherence
真正的问题是False sharing。使用属于同一chache行的内存元素的两个或多个线程将为共享资源进行编译,并且可能非常慢。