gpt4 book ai didi

c - SMP 架构中的 pthread_create(3) 和内存同步保证

转载 作者:太空宇宙 更新时间:2023-11-04 02:04:33 25 4
gpt4 key购买 nike

我正在查看 The Open Group Base Specifications Issue 7 (IEEE Std 1003.1, 2013 Edition), section 4.11 的第 4.11 节文档,其中详细说明了内存同步规则。这是我为详细说明 POSIX/C 内存模型而设法获得的 POSIX 标准中最具体的。

这是一段话

4.11 Memory Synchronization

Applications shall ensure that access to any memory location by more than one thread of control (threads or processes) is restricted such that no thread of control can read or modify a memory location while another thread of control may be modifying it. Such access is restricted using functions that synchronize thread execution and also synchronize memory with respect to other threads. The following functions synchronize memory with respect to other threads:

fork() pthread_barrier_wait() pthread_cond_broadcast() pthread_cond_signal() pthread_cond_timedwait() pthread_cond_wait() pthread_create() pthread_join() pthread_mutex_lock() pthread_mutex_timedlock()

pthread_mutex_trylock() pthread_mutex_unlock() pthread_spin_lock() pthread_spin_trylock() pthread_spin_unlock() pthread_rwlock_rdlock() pthread_rwlock_timedrdlock() pthread_rwlock_timedwrlock() pthread_rwlock_tryrdlock() pthread_rwlock_trywrlock()

pthread_rwlock_unlock() pthread_rwlock_wrlock() sem_post() sem_timedwait() sem_trywait() sem_wait() semctl() semop() wait() waitpid()

(省略要求的异常(exception)情况)。

基本上,解释上述文档,规则是当应用程序读取或修改内存位置而另一个线程或进程可能修改它时,它们应该确保同步线程执行和内存 相对于其他线程 通过调用列出的函数之一。其中,pthread_create(3)提到提供内存同步。

我知道这基本上意味着需要某种 memory barrier每个功能都隐含(尽管标准似乎不使用该概念)。因此,例如从 pthread_create() 返回,我们可以保证该线程在调用之前所做的内存修改在其他线程(运行可能不同的 CPU/内核)也同步内存之后出现。但是新创建的线程呢 - 在线程开始运行线程函数之前是否存在隐含的内存屏障,以便它始终看到由 pthread_create() 同步的内存修改?这是标准规定的吗?或者我们是否应该显式提供内存同步,以便能够根据 POSIX 标准信任我们读取的任何数据的正确性?

特殊情况(作为特殊情况回答上述问题):上下文切换是否提供内存同步,即,当进程或线程的执行开始或恢复时,内存是否相对于任何同步其他执行线程的内存同步?

示例:

Thread #1 创建一个从堆中分配的常量对象。线程 #1 创建一个新线程 #2 从对象中读取数据。如果我们可以假设新线程 #2 以内存同步开始,那么一切都很好。但是,如果运行新线程的 CPU 核心具有先前分配的副本,但由于在其高速缓存内存中丢弃了数据而不是新值,那么它可能有错误的状态 View ,并且应用程序可能无法正常运行。

更具体...

  1. 之前在程序中(这是CPU#1缓存中的值)

     int i = 0;        
  2. 线程 T0CPU #0 中运行:

     pthread_mutex_lock(...);
    int tmp = i;
    pthread_mutex_unlock(...);
  3. CPU #1 中运行的线程 T1:

     i = 42;
    pthread_create(...);
  4. 新创建的线程 T2CPU #0 中运行:

     printf("i=%d\n", i);    /* First step in the thread function */

没有内存屏障,没有同步线程 T2 内存,输出可能会是

     i=0

(以前缓存的,未同步的值)。

更新:如果允许这种疯狂的实现,许多使用 POSIX 线程库的应用程序将不是线程安全的。

最佳答案

is there implied memory barrier before the thread starts running the thread function so that it unfailingly sees the memory modifications synchronized by pthread_create()?

是的。否则,pthread_create 就没有意义充当内存同步(屏障)。

(这是 afaik。posix 没有明确说明,(nor does posix define a standard memory model),所以你必须决定你是否相信你的实现会做它可能做的唯一理智的事情——确保在新线程运行之前同步——我不会特别担心它)。

Special case (which would as a special case answer the above question): does a context switch provide memory synchronization, that is, when the execution of a process or thread is started or resumed, is the memory synchronized with respect to any memory synchronization by other threads of execution?

不,上下文切换不作为障碍。

Thread #1 creates a constant object allocated from heap. Thread #1 creates a new thread #2 that reads the data from the object. If we can assume the new thread #2 starts with memory synchronized then everything is fine. However, if the CPU core running the new thread has copy of previously allocated but since discarded data in its cache memory instead of the new value, then it might have wrong view of the state and the application may function incorrectly.

由于pthread_create必须进行内存同步,所以不能发生这种情况。驻留在另一个核心上的 cpu 缓存中的任何旧内存都必须失效。 (幸运的是,常用的平台是缓存一致的,所以硬件会负责)。

现在,如果您在创建 2. 线程后更改对象,则需要再次进行内存同步,以便所有各方都能看到更改,否则会避免竞争条件。 pthread 互斥量通常用于实现这一点。

关于c - SMP 架构中的 pthread_create(3) 和内存同步保证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22347856/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com