我试图在多线程产生和单线程消耗的情况下找出互斥和条件变量的执行。
以下是示例代码:
#include <iostream>
#include <string>
int main()
{
std::string countries[] = {"Germany", "India", "Korea"};
int country_number;
std::cin >> country_number; // invalid input is not being checked
// array indexing starts from 0
std::cout << "You selected " << countries[country_number - 1] << std::endl;
return 0;
}
在这段代码中,我期待thread1等待条件变量完成。所以,thread2或thread3当任何一个启动并获得互斥和chanegs为1.它必须发出正在等待的thread1,并且thread1将开始执行。
但是,我看到即使thread1正在等待条件变量done = 0并且在来自thread2的信号之后,我为thread2方法创建的另一个线程获得了互斥锁。
我想知道我对输出的期望是否有任何问题。我正在尝试使用类似的情况实现阻塞队列,其中可以有多个生产者和单个消费者。
谢谢, Poovannan。
答案 0 :(得分:1)
你的期望是错误的。线程1将最终唤醒并获取互斥锁,因为它已被发出信号,但不能保证线程3不会首先到达那里。
如果您不希望生产者线程在队列已满时“生成”(此处,您的队列长度为1),那么您还需要让它们等待 - 您可以使用第二个条件变量的是:
int done = 0;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c_done = PTHREAD_COND_INITIALIZER;
pthread_cond_t c_undone = PTHREAD_COND_INITIALIZER;
void *thr2(void *arg)
{
pthread_mutex_lock(&m);
/* wait for done to be zero */
while (done != 0)
pthread_cond_wait(&c_undone, &m);
done = 1;
pthread_cond_signal(&c_done);
pthread_mutex_unlock(&m);
return NULL;
}
void *thr1(void *arg)
{
pthread_mutex_lock(&m);
while (done == 0)
{
pthread_cond_wait(&c_done, &m);
}
done = 0;
pthread_cond_signal(&c_undone);
pthread_mutex_unlock(&m);
}
答案 1 :(得分:0)
来自官方POSIX pthread_cond_signal
reference:
pthread_cond_signal()
函数将取消阻止至少一个在指定条件变量cond
上阻塞的线程
和
如果在条件变量上阻塞了多个线程,则调度策略应确定线程被解除阻塞的顺序
这意味着你无法真正告诉信号会唤醒哪个线程。如果你只想唤醒一个特定的线程,你必须使用一个特定于该线程的条件变量。
答案 2 :(得分:0)
我们假设thr1
首先开始。 thr1
锁定互斥锁并等待条件,并在进入等待之前释放互斥锁m
。 m
可用于thread2或thread3。 thread2或thread3中的一个将锁定互斥锁并设置done
并发出信号thr1
并释放互斥锁。但是thr1
不一定能够重新获取互斥锁m
,因为另一个线程可能已经获得了互斥锁。
即使条件thr1
等待是真的(done
被thread2或thread3设置为1
,它也不会返回,直到它可以再次锁定互斥锁。请记住pthread_cond_wait()
在返回之前锁定互斥锁。这意味着thr1
仍在等待。
另一点是thr1
完成时应返回NULL
或致电pthread_exit()
。请注意,sleep
不是一个好的同步机制。