所有线程都具有相同的全局变量吗?

Do all threads have the same global variable?

我在尝试使用信号量实现线程同步问题时遇到了一个常见问题。我不想涉及太多(不相关的)细节,所以我将提供我认为对澄清我的问题很重要的代码。

sem_t *mysema;
violatile int counter;

struct my_info{
    pthread_t t;
    int id;
};

void *barrier (void *arg){
    struct my_info *a = arg;
    arg->id = thrid;
    
    while(counter >0){
        do_work(&mysem[thrid])

        sem_wait(&mysema[third])
        
        display_my_work(arg);
        counter--;
        sem_post(&mysema[thrid+1])
    }   
    return NULL;            
}           

int main(int argc, char *argv[]){

    int N = atoi(argv[1]);
    mysema = mallon(N*(*mysema));
    counter = 50;
    /*semaphore intialisations */
    for(i=0; i<M; i++){
        sem_init(&mysema[i],0,0);
    }
    
    for(i=0; i<M; i++){
        mysema[i].id = i;
    }
    
    for(i=0; i<M; i++){
        pthread_create(&mysema.t[i], NULL, barrier, &tinfo[i])
    }   
    /*init wake up the first sempahore */
    sem_post(&mysema[0]);   
.
.
.

我们有一个由在 0 中初始化的 M 个信号量组成的数组,其中 M 由用户在命令行中定义。
当所有 M 个线程总共完成一些必要的计算 50 次时,我知道我完成了。
每个线程阻塞自己,直到前一个线程“sem_post's”为止。第一个线程将被 init 唤醒。
我的问题是线程是否会在“'counter = 0 '”时停止。 他们是否都看到了相同的变量——counter?(它是一个全局变量,在 main 中初始化)。
如果线程为零,则第一次“counter = 49”让所有其他线程(线程 1、2、...M-1)看到?

这些是不同的问题:

Do [the threads] all see the same variable - counter? (It is a global one, initialised in the main).

If thread zero , makes the very first time ```counter = 49''' do all the other threads( thread 1, 2, ...M-1) see that ?

第一个很简单:是的。在文件范围内声明且没有存储 class 说明符 _Thread_local 的对象是单个对象,其存储持续时间为程序的整个 运行。只要该对象的标识符在范围内且可见,无论哪个线程正在访问它,它都会标识同一个对象。

第二个问题的答案比较复杂。在多线程程序中存在数据竞争的可能性,并且包含数据竞争的程序的行为是未定义的。 volatile 限定符不能防止这些;相反,您需要对每个共享变量的所有访问进行适当的同步,包括读取和写入。这可以由信号量提供,或者更常见的是互斥量,以及其他可能性。

您的代码减少 counter 可能 得到充分保护,但我怀疑不会,因为线程使用不同的信号量。如果这允许多个不同的线程执行 ...

        display_my_work(arg);
        counter--;

... 线路同时存在,那么您就会发生数据竞争。然而,即使你在那里的保护足够,在 while 条件下读取 counter 显然没有正确同步,你肯定在那里有数据竞争。

数据竞争带来的未定义行为的常见表现之一是线程看不到彼此的更新,因此您的程序的未定义行为通常不仅意味着线程 1 ... M-1 可能看不到线程 0 对 counter 的更新,它也特别是 使这种故障相对可能发生。