我是线程新手我想使用ptherad_cond_signal&pthread_cond_wait检查某些情况我有这个代码作为示例:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int x = 0;
void* f1(void *arg){
for (int i = 0; i < 10; i++)
{
pthread_mutex_lock(&lock);
x += 10;
printf("%dn", x);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
return NULL;
}
void* f2(void* arg){
pthread_mutex_lock(&lock);
while (x < 40)
{
pthread_cond_wait(&cond, &lock);
}
x -= 40;
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char *args[]){
pthread_t p1, p2;
pthread_create(&p2, NULL, f2, NULL);
pthread_create(&p1, NULL, f1, NULL);
pthread_exit(NULL);
return 0;
}
结果:
10
20
30
40
50
60
70
80
90
100
但我期待:
10
20
30
40
10
20
30
40
50
60
为什么在pthread_cond_signal之后,函数f2不继续?
它似乎在f1循环中,在pthread_cond_wait唤醒之前再次锁定
您的第一个问题是main
创建了两个线程,但可能会在其他两个线程完成之前退出(并退出您的程序(。Linux构建中的线程等待所有线程完成,然后在main返回时退出进程,这可能存在细微差别。我总是忘记这里的规则,但这是main
等待子线程完成的首选模式。这是一个简单的改变
int main(int argc, char *args[]){
pthread_t p1, p2;
pthread_create(&p2, NULL, f2, NULL);
pthread_create(&p1, NULL, f1, NULL);
// wait for both threads to complete
pthread_join(&p1, NULL);
pthread_join(&p2, NULL);
return 0;
}
回到你原来的问题。
在上下文切换到f2
之前,没有任何东西阻止f1
递增到100。
听起来你想要的是f1
将X增加到40,然后等待f2
将其降回,然后再次将增量间隔增加到60。
您可以很容易地在两个线程中使用您的条件变量来获得更改通知并等待另一个线程。
我重构了你的一些代码,这样我就不必一遍又一遍地重写同一个块了。但它仍然主要是您的原始代码。
void IncrementX(int val)
{
pthread_mutex_lock(&lock);
x += 10;
printf("%dn", x);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
void WaitForX(int target, int gt)
{
pthread_mutex_lock(&lock);
while ((x >= target && gt) || (x < target && !gt))
{
pthread_cond_wait(&cond, &lock);
}
pthread_mutex_unlock(&lock);
}
void* f1(void *arg){
// increment to 40
for (int i = 0; i < 4; i++)
{
IncrementX(10);
}
WaitForX(40, 0); // wait for X to drop below 40
// increment back to 60
for (int i = 0; i < 6; i++)
{
IncrementX(10);
}
return NULL;
}
void* f2(void* arg){
WaitForX(40, 1); // wait for X to go to 40 or above
IncrementX(-40);
return NULL;
}