这个程序有同步问题吗

Is there any synchronization problem in this program

考虑以下程序。
(i) A 行和 B 行的输出是什么?证明你的答案。
(ii) 您认为更新变量值是否存在同步问题?
证明你的答案。

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>

int value = 100;
void *thread_prog(void *param);

int main(int argc, char *argv[])
{
    pthread_t tid;
    pthread_create(&tid, NULL, thread_prog, NULL);
    pthread_join(tid, NULL);
    value = value + 100;
    printf("Parent value = %d\n", value); //Line A
}
void *thread_prog(void *param)
{
    value = value + 100;
    printf("Child value = %d\n", value); // Line B
    pthread_exit(0);
}

输出将是 A 行是 300,B 行是 200 我不认为存在同步问题,因为 pthread_join(tid, NULL);

您假设没有同步问题是正确的,pthread_join() 会挂起调用线程,直到目标线程终止。如果目标线程已经终止,它会立即returns。在任何情况下,目标案例都在输出 A 行之前执行并终止。

在发布的代码中,控制流很明显,因此前后顺序关系没有问题。但是多线程代码的正确同步需要的不仅仅是建立正确的前后关系。

还有两个额外的方面需要解决以确保此代码没有同步问题。

这个回答只解决了第一个问题。

仅在多线程代码中建立保证运行前后关系来确保另一个线程可以完整地看到对变量的更改是不够的。 Wikipedia entry on "memory barrier" provides a good explanation:

A memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction that causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction. This typically means that operations issued prior to the barrier are guaranteed to be performed before operations issued after the barrier.

Memory barriers are necessary because most modern CPUs employ performance optimizations that can result in out-of-order execution. This reordering of memory operations (loads and stores) normally goes unnoticed within a single thread of execution, but can cause unpredictable behaviour in concurrent programs and device drivers unless carefully controlled. The exact nature of an ordering constraint is hardware dependent and defined by the architecture's memory ordering model. Some architectures provide multiple barriers for enforcing different ordering constraints.

换句话说,例如 CPU 1 上对变量 运行 所做的更改可能不会被另一个线程 运行 上的更改“看到”,比如说 CPU 7 即使代码在 CPU 7 上运行在 CPU 1.

上更改变量 运行 的代码之后

需要某种特定于平台的实现,以确保此类更改通过实际硬件传播并可见。

并且 POSIX 的线程模型指定了那些确切的 gua运行tee。

Per POSIX 4.12 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:

 .
 .
 .
pthread_create()
pthread_join()
 .
 .
 .

pthread_create()pthread_join() 的使用不仅建立了正确同步所需的前后顺序关系,而且根据 POSIX 标准,它们还建立了可见性要求。

所以,是的,发布的代码在 gua运行前后顺序和可见性方面得到了正确同步。

但是请注意,此答案并未解决发布的代码是否根据 C 抽象机的语义正确同步的问题。在这方面,我会遵从对 C 标准及其抽象机的解释有更好理解的专家。