使用条件变量进行线程间通信?

时间:2017-06-27 03:54:10

标签: c multithreading pthreads

假设我在一个进程中有三个线程th1,th2和th3以及三个寄存器(数组)a,b和c。 th1和th2只写入三个寄存器之一,th3只读取这些寄存器中的数据。 th1,th2和th3将以等待条件变量的连续顺序b / c工作。两个条件变量cv1和cv2分别用于(th1,th2)和(th2,th3)之间的信令。工作程序如下:

  1. 首先将一些东西写入' a'数组,然后发信号(使用cv1)th2等待它。
  2. 从th1接收到信号后,th2开始写入同一个数组,' a'然后发信号(使用cv2)th3进行读取' a'。
  3. th3开始阅读' a' (相同的阵列)接收来自th2的信号。
  4. 以上3个步骤重复' b'和' c'以同样的方式。
  5. 我的c代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <pthread.h>
    
    void* th1();
    void* th2();
    void* th3();
    
    int a[40], b[40], c[40], rn;
    
    pthread_mutex_t mutex1, mutex2, mutex3;
    pthread_cond_t cv1, cv2;
    
    int main()
    {
        pthread_t  t[3];
        pthread_mutex_init(&mutex1, NULL);
        pthread_mutex_init(&mutex2, NULL);
        pthread_mutex_init(&mutex3, NULL);
    
        pthread_cond_init(&cv1, NULL);
        pthread_cond_init(&cv2, NULL);
    
        pthread_create(&t[0], NULL, th1, NULL);
        pthread_create(&t[1], NULL, th2, NULL);
        pthread_create(&t[2], NULL, th3, NULL);
    
    
        pthread_join(t[0], NULL);
        pthread_join(t[1], NULL);
        pthread_join(t[2], NULL);
    
        pthread_mutex_destroy(&mutex1);
        pthread_mutex_destroy(&mutex2);
        pthread_mutex_destroy(&mutex3);
        pthread_cond_destroy(&cv1);
        pthread_cond_destroy(&cv2);
        return 0;
    }
    
    void* th1()
    {       
        pthread_mutex_lock(&mutex1);
            for(int i=0; i<20; i++)
            {
                a[i]=i;
                }
            pthread_cond_signal(&cv1);
            puts("a signal sent...");
        pthread_mutex_unlock(&mutex1);
    
    
        pthread_mutex_lock(&mutex2);
            for(int i=0; i<20; i++)
            {
                b[i]=i;
                }
            pthread_cond_signal(&cv1);
            puts("b signal sent...");
        pthread_mutex_unlock(&mutex2);
    
    
        pthread_mutex_lock(&mutex3);
            for(int i=0; i<20; i++)
            {
                c[i]=i;
                }
            pthread_cond_signal(&cv1);
            puts("c signal sent...");
        pthread_mutex_unlock(&mutex3);
    
        pthread_exit(NULL);
    }
    
    void* th2()
    {
        pthread_mutex_lock(&mutex1);
            pthread_cond_wait(&cv1, &mutex1);
            puts("signal recv form th1 for writing 'a'...\n");
            for(int i=0; i<=20; i++)
            {
                a[i+20]=i+20;
            }
            pthread_cond_signal(&cv2);
        pthread_mutex_unlock(&mutex1);
    
    
        pthread_mutex_lock(&mutex2);
            pthread_cond_wait(&cv1, &mutex2);
            puts("signal recv from th1 for writing 'b'...\n");
            for(int i=0; i<=20; i++)
            {
                b[i+20]=i+20;
            }
            pthread_cond_signal(&cv2);
        pthread_mutex_unlock(&mutex2);
    
    
        pthread_mutex_lock(&mutex3);
            pthread_cond_wait(&cv1, &mutex3);
            puts("signal recv from th1 for writing 'c'...\n");
            for(int i=0; i<=20; i++)
            {
                c[i+20]=i+20;
            }
            pthread_cond_signal(&cv2);
        pthread_mutex_unlock(&mutex3);
    
        pthread_exit(NULL);
    }
    void* th3()
    {
    
        pthread_mutex_lock(&mutex1);
            pthread_cond_wait(&cv2, &mutex1);
            puts(" signal recv from th2 for reading 'a'...\n");
            for(int i=0; i<=40; i++)
            {
                printf("%d   :",a[i]);
            }
            printf("\n\n");
        pthread_mutex_unlock(&mutex1);
    
    
        pthread_mutex_lock(&mutex2);
            pthread_cond_wait(&cv2, &mutex2);
            puts(" signal recv from th2 for reading 'b'...\n");
            for(int i=0; i<=40; i++)
            {
                printf("%d   :",b[i]);
            }
            printf("\n\n");
        pthread_mutex_unlock(&mutex2);
    
    
        pthread_mutex_lock(&mutex3);
            pthread_cond_wait(&cv2, &mutex3);
            puts(" signal recv from th2 for reading 'c'...\n");
            for(int i=0; i<=40; i++)
            {
                printf("%d   :",c[i]);
            }
            printf("\n\n");
        pthread_mutex_unlock(&mutex3);
    
        pthread_exit(NULL);
    
    }
    

    显示后输出块:

    mohtashim-ul-haq@mohtashim-pc:~/Documents/rough$ gcc tread.c -o tread -lpthread
    mohtashim-ul-haq@mohtashim-pc:~/Documents/rough$ ./tread
    a signal sent...
    b signal sent...
    c signal sent...
    

    我的预期输出类似于:

        a signal sent
        signal recv form th1 for writing 'a'...
        signal recv from th2 for reading 'a'...
        1 2 3 4 ..... 40
    
        b signal sent
        signal recv form th1 for writing 'b'...
        signal recv from th2 for reading 'b'...
        1 2 3 4 ..... 40
    
        c signal sent
        signal recv form th1 for writing 'c'...
        signal recv from th2 for reading 'c'...
        1 2 3 4 ..... 40
    

    我认为,我无法理解条件变量如何与互斥锁一起使用。任何帮助???

1 个答案:

答案 0 :(得分:0)

您需要整合事件&#34;信号&#34;,如果发出信号(通知状态变化),您需要存储。

对于第一个事件(&#34; a&#34;读取),对代码的调整可能如下所示:

int a_read = 0; /* to store the event "a had been read" actually happened */

void* th1(void * pvunused)
{       
    pthread_mutex_lock(&mutex1);
    for(int i=0; i<20; i++)
    {
        a[i]=i;
    }

    a_read = 1;
    pthread_cond_signal(&cv1);
    ...


void* th2(void * pvunused)
{
  pthread_mutex_lock(&mutex1);
  while (0 == a_read) /* Theoretical an "if" would do here, 
                         using "while" lets you stay on the safe side, in case
                         a "spurious wake-up" (https://en.wikipedia.org/wiki/Spurious_wakeup)
                         occurred. */
  {
    pthread_cond_wait(&cv1, &mutex1);
  }

  ...