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