我有一个C线程程序,要反复打印下面的字串。
one two three one two three one two three...
我想测试一下如何用条件变量来完成这个任务 所以我使用了下面的代码。
#include <stdio.h>
#include <pthread.h>
#include <string.h>
pthread_cond_t c1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t c2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t c3 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
char arr[15] = "one";
void *printS(void *str)
{
while(1)
{
pthread_mutex_lock(&m);
if ( strcmp(arr,str) != 0)
{
if(strcmp("one",str) == 0)
{
pthread_cond_wait(&c1, &m);
}
else if(strcmp("two",str) == 0)
{
pthread_cond_wait(&c2, &m);
}
else if(strcmp("three",str) == 0)
{
pthread_cond_wait(&c3, &m);
}
}
printf("%s ", (char*)str);
if (strcmp("one",arr) == 0)
{
strcpy(arr,"two");
pthread_cond_signal(&c2);
}
else if (strcmp("two", arr) == 0)
{
strcpy(arr,"three");
pthread_cond_signal(&c3);
}
else if (strcmp("three", arr) == 0)
{
strcpy(arr,"one");
pthread_cond_signal(&c1);
}
pthread_mutex_unlock(&m);
}
return NULL;
}
int main()
{
pthread_t t1, t2, t3;
const char ch1[] = "one";
const char ch2[] = "two";
const char ch3[] = "three";
pthread_mutex_init(&m,0);
pthread_cond_init(&c1, 0);
pthread_cond_init(&c2, 0);
pthread_cond_init(&c3, 0);
pthread_create(&t1, NULL, printS, (void *)ch1);
pthread_create(&t2, NULL, printS, (void *)ch2);
pthread_create(&t3, NULL, printS, (void *)ch3);
pthread_join(t1, 0);
pthread_join(t2, 0);
pthread_join(t3, 0);
while(1);
return 0;
}
然而,用这段代码我得到了以下(不需要的)输出。
three three three three three three three one two three one two three one tho three three three three three three
我似乎找不到同步化或代码结构的问题。任何帮助都是感激不尽的,谢谢你!!
就像一般-评论里问的那样,你需要一个mutex,一个cv,就可以了。每个线程都已经得到了自己的谓词测试值。你所需要做的就是确保mutex被锁定(通过初始输入或通过从 pthread_cond_wait
),并检查谓词状态,采取相应的行动。打印后,再改变谓词(字符串),在条件改变时广播其他线程,然后再循环。另外,mutex锁应该是在进入while-loop之前。cond-wait会根据需要解锁。
#include <stdio.h>
#include <pthread.h>
#include <string.h>
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
char arr[15] = "one";
void *printS(void *str)
{
pthread_mutex_lock(&m);
while(1)
{
// mutex is latched already
while (strcmp(arr,str) != 0)
{
// this will unlatch the mutex and begin waiting on cv
pthread_cond_wait(&cv, &m);
}
// mutex is once-again latched.
printf("%s ", (char*)str);
// change string accordingly
if (strcmp("one",arr) == 0)
strcpy(arr,"two");
else if (strcmp("two", arr) == 0)
strcpy(arr,"three");
else if (strcmp("three", arr) == 0)
strcpy(arr,"one");
// and tell everyone waiting something happened.
// they will wake up as soon as we hit the next wait.
pthread_cond_broadcast(&cv);
}
// will never be reached, but good form nonetheless.
pthread_mutex_unlock(&m);
return NULL;
}
int main()
{
pthread_t t1, t2, t3;
char ch1[] = "one";
char ch2[] = "two";
char ch3[] = "three";
pthread_create(&t1, NULL, printS, ch1);
pthread_create(&t2, NULL, printS, ch2);
pthread_create(&t3, NULL, printS, ch3);
pthread_join(t1, 0);
pthread_join(t2, 0);
pthread_join(t3, 0);
fgetc(stdin);
return 0;
}