条件变量来回发送

时间:2014-04-19 17:12:57

标签: c multithreading pthreads condition-variable

我有一个程序,我希望能够在不同的线程之间进行。在这个例子中,我只是尝试从字符串中打印东西,从另一个字符串中填充东西只是为了看到我在两个线程之间发送。我无法用我的代码执行此操作,因为它挂起了。理想情况下,我想使用多个信号,并能够来回走动。我花了大约四个小时才完成这项工作,我只是无法让它工作,我认为只使用全局变量会更简单,然后我只需要使用互斥量而不是条件变量,或者甚至根本没有互斥。

我无法让这些变化无常的互斥和条件变量按预期运行。

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

char word1[10] = "Hello";
char word2[10] = "world";

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // mutual exclusion lock for prod
//pthread_mutex_t mutexSigalProd = PTHREAD_MUTEX_INITIALIZER;
//pthread_cond_t signalToProd = PTHREAD_COND_INITIALIZER;
pthread_cond_t addToQ = PTHREAD_COND_INITIALIZER;


void * prod(void *arg) { printf("Entering prod \n");
    pthread_mutex_lock(&mutex);
    int i = 0;

    while (i < 10) {
        printf("PROD adding line: %c \t", word1[i]);
        i++;
        if (i % 2 == 0)
        {
            pthread_mutex_unlock(&mutex);
            pthread_cond_signal(&addToQ);
            pthread_cond_wait(&addToQ, &mutex);
        }
    }
    pthread_exit(NULL);
}


void * con(void *arg) 
{
    printf("Entering con \n");
    pthread_mutex_lock(&mutex);
    //pthread_mutex_unlock(&mutex);
    pthread_cond_wait(&addToQ, &mutex);
    int i = 0;

    while (i < 10) 
    {
        printf ("CON adding line: %c \t", word2[i]);
        i++;
        if (i % 2 != 0)
        {
            //pthread_mutex_unlock(&mutex);
            pthread_cond_signal(&addToQ);
            pthread_cond_wait(&addToQ, &mutex);
        }
    }

    pthread_exit(NULL);
}

int main()
{
    pthread_t threadp1;        // Thread objects
    pthread_t threadp2;
    pthread_t threadc1;

    pthread_create(&threadp1, NULL, prod, NULL);  // start first producer thread
    //pthread_create(&threadp2, NULL, con1, NULL); // start second producer thread
    pthread_create(&threadc1, NULL, con,  NULL); // start consumer thread
    pthread_exit(NULL);              // main thread quits
}

1 个答案:

答案 0 :(得分:1)

代码中的竞争条件是:

Prod发送信号而不检查Con是否在等待它。如果Con尚未等待信号,则信号无效(来自手册页 - &#34;如果cond上当前没有线程被阻止,则pthread_cond_broadcast()和pthread_cond_signal()函数将不起作用。 #34;。)

然后你让Con和Prod都互相等待。因此陷入僵局。

查看以下代码是否有效:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sched.h>

char word1[10] = "Hello";
char word2[10] = "world";
int con_started = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // mutual exclusion lock for prod
pthread_cond_t addToQ = PTHREAD_COND_INITIALIZER;

void * prod(void *arg) {
    printf("PROD: Entering prod \n");
    fflush(stdout);
    int i = 0;
    int j = 1;
    while (i < 5) {
        printf("PROD adding line: %c \n", word1[i]);
        fflush(stdout);
        i++;
        if (i % 2 == 0)
        {
            pthread_mutex_lock(&mutex);
            while(!con_started)
            {
                pthread_mutex_unlock(&mutex);
                sched_yield();
                printf("PROD: Waiting for CON to wait.\n");
                fflush(stdout);
                pthread_mutex_lock(&mutex);
            }
            printf("PROD: Sending signal %d\n\n", j);
            fflush(stdout);
            pthread_cond_signal(&addToQ);
            printf("PROD: Will wait now \n\n");
            fflush(stdout);
            pthread_cond_wait(&addToQ, &mutex);
            printf("PROD received signal %d\n\n", j);
            fflush(stdout);
            pthread_mutex_unlock(&mutex);
            j++;
        }
    }
    sched_yield();
    sleep(1);
    printf("PROD: Sending signal %d\n\n", j);
    fflush(stdout);
    pthread_cond_signal(&addToQ);
    pthread_exit(NULL);
}


void * con(void *arg)
{
    int i = 0;
    int j=1;
    printf("CON: Entering con \n");
    fflush(stdout);
    pthread_mutex_lock(&mutex);
    con_started = 1;
    printf("CON: Will wait now\n \n");
    fflush(stdout);
    pthread_cond_wait(&addToQ, &mutex);
    printf("CON received first signal\n\n");
    fflush(stdout);
    while (i < 5)
    {
        printf ("CON adding line: %c \n", word2[i]);
        fflush(stdout);
        if (i % 2 != 0)
        {
            //pthread_mutex_unlock(&mutex);
            printf("CON: Sending signal %d\n\n", j);
            fflush(stdout);
            pthread_cond_signal(&addToQ);
            j++;
            printf("CON: Will wait now \n\n");
            fflush(stdout);
            pthread_cond_wait(&addToQ, &mutex);
            printf("CON received signal %d\n\n", j);
            fflush(stdout);
            pthread_mutex_unlock(&mutex);
        }
        i++;
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t threadp1;        // Thread objects
    pthread_t threadc1;
    pthread_create(&threadp1, NULL, prod, NULL);  // start first producer thread
    pthread_create(&threadc1, NULL, con,  NULL); // start consumer thread
    pthread_join(threadp1, NULL);
    printf("MAIN: threadp1 completed.\n");
    fflush(stdout);
    pthread_join(threadc1, NULL);
    printf("MAIN: threadc1 completed.\n");
    fflush(stdout);
}