【问题标题】:Pthread Synchronization with conditional variablesPthread 与条件变量同步
【发布时间】:2019-04-05 05:45:30
【问题描述】:

我正在通过使用互斥锁和条件变量来练习 pthread 同步。在下面的代码中,我创建了 3 个线程,我希望看到输出告诉执行哪个线程,然后从主线程退出以报告计数的值。但是,我观察到我可以有 3 个不同的输出。 这是我的代码:

#include<stdio.h> 
#include<string.h> 
#include<pthread.h> 
#include<stdlib.h> 
#include<unistd.h> 


typedef struct node{

    int data;
    struct node* next;

}LinkList;

LinkList *list = NULL ;
//LinkList *head;
int count;
int enter;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void* trythis(void *arg) 
{ 
    pthread_mutex_lock(&lock);
    //enter = 0;
    printf("Thread sleeps... \n");
    while(!enter){
        pthread_cond_wait(&cond,&lock);
    }
    enter = 1;
    printf("Thread %d Enter = %d\n",count++,enter);
    pthread_cond_signal(&cond);


    pthread_mutex_unlock(&lock);

    return NULL; 
} 

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

    pthread_t tid[3];
    int error;
    int i = 0;
    printf("Main Beginning1\n");
    int p = pthread_mutex_init(&lock,NULL);

    if(p != 0){
        printf("Mutex failed \n");
        exit(1);
    }
    printf("Main Beginning2\n");
    while(i < 3) 
    { 
        error = pthread_create(&(tid[i]), NULL, &trythis, NULL); 
        if (error != 0) 
            printf("\nThread can't be created : [%s]", strerror(error)); 
        i++; 
    } 
    printf("Main Beginning3\n");
    /*for(int i = 0; i < 3; i++){
        pthread_join(tid[i], NULL); 
    }*/
    printf("Main Beginning4\n");
    pthread_mutex_lock(&lock);
    enter = 1;
    printf("Main Beginning\n");
    while(count < 2){

        pthread_cond_wait(&cond,&lock);
        printf("count : %d\n",count);
    }

    pthread_cond_signal(&cond);
    printf("Main count = %d\n",count);

    pthread_mutex_unlock(&lock);



    pthread_mutex_destroy(&lock);

    return 0;
}

我的输出是:

***FIRST OUTPUT***
oguzliv@oguzliv-VirtualBox:~/Desktop/OSindAir$ ./linklist 
Main Beginning1
Main Beginning2
Thread sleeps... 
Main Beginning3
Thread sleeps... 
Main Beginning4
Main Beginning
Thread sleeps... 
Thread 0 Enter = 1
Thread 1 Enter = 1
Thread 2 Enter = 1
count : 3
Main count = 3

***SECOND OUTPUT***
oguzliv@oguzliv-VirtualBox:~/Desktop/OSindAir$ ./linklist 
Main Beginning1
Main Beginning2
Thread sleeps... 
Main Beginning3
Main Beginning4
Main Beginning
Thread sleeps... 
Thread 0 Enter = 1
Thread sleeps... 
Thread 1 Enter = 1
count : 2
Main count = 2

***THIRD OUTPUT***
oguzliv@oguzliv-VirtualBox:~/Desktop/OSindAir$ ./linklist 
Main Beginning1
Main Beginning2
Thread sleeps... 
Thread sleeps... 
Main Beginning3
Main Beginning4
Thread sleeps... 
Main Beginning
(waits infinitely)

我不知道这些输出的原因。请帮我。顺便说一句,这段代码是独立于链接列表结构的。

--------编辑-----

经过一番研究,我按预期执行了代码,感谢此链接的所有者https://gist.github.com/rtv/4989304

但是,我仍然对我以前的代码感到困惑,为什么它不能像编辑的那样执行。全部改变的是:

while(!enter){
        pthread_cond_wait(&cond,&lock);
    }
    enter = 1;
    printf("Thread %d Enter = %d\n",count++,enter);
    pthread_cond_signal(&cond);

const int myid = long(args);
printf("Thread sleeps with ID : %d\n",myid);
pthread_mutex_lock(&lock);
count++;
printf("Thread ID : %d count : %d",myid,count);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);

return NULL;

【问题讨论】:

  • 请添加语言标签,例如C。非常了解该语言的人通常使用语言标签来过滤问题,因此可以更快地找到并回答您的问题。
  • 感谢告知

标签: c multithreading operating-system synchronization


【解决方案1】:

从根本上说,您的原始代码正在与 enter 的值竞争。考虑两种情况:

  1. 您的实现优先考虑新创建的线程。因此,只要调用 pthread_create(),trythis() 就会开始执行,获取互斥体,发现 !enter,并等待 cond 发出信号。这发生在每个线程上。然后 main 抓取互斥体,将 enter 设置为 1,然后等待 cond 发出信号。谁来叫醒他们?这种类型的同步失败过去被称为阴谋,但该术语已不再使用。
  2. 您的实现优先考虑正在运行的线程。因此,pthread_create() 构造了 trythis(),但 trythis 还没有开始执行。当 main 完成创建线程时,它会获取互斥体,将 enter 设置为 1,然后等待 cond 发出信号。由于它正在等待(不再运行),其他线程启动,并且每个线程都获取互斥锁,发现 enter 不为零,因此发出条件信号,删除互斥锁并退出。其中一个会唤醒 main,因为它是唯一等待的线程,当它唤醒时发现 count > 2,按预期退出循环。

现实世界可以是这些的任意混合,因此您可能会发现您留下 0..3 个线程和/或 main 阻塞。我认为答案是你在 main 中的一行:

pthread_mutex_lock(&lock);
enter = 1;

应该添加:

pthread_cond_signal(&cond);

这样,任何已经在等待进入的人都会被释放。 从流量的角度来看; “trythis”正在消耗输入,并产生计数; "main" 正在产生输入,并消耗计数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2012-07-02
    • 2017-09-27
    • 2020-09-13
    • 2014-01-13
    相关资源
    最近更新 更多