我有一些目前看起来像这样的代码(简化)
/* instance in global var *mystruct, count initialized to 0 */
typedef struct {
volatile unsigned int count;
} mystruct_t;
pthread_mutex_t mymutex; // is initialized
/* one thread, goal: block while mystruct->count == 0 */
void x(void *n) {
while(1) {
pthread_mutex_lock(&mymutex);
if(mystruct->count != 0) break;
pthread_mutex_unlock(&mymutex);
}
pthread_mutex_unlock(&mymutex);
printf("count no longer equals zero");
pthread_exit((void*) 0)
}
/* another thread */
void y(void *n) {
sleep(10);
pthread_mutex_lock(&mymutex);
mystruct->count = 10;
pthread_mutex_unlock(&mymutex);
}
这对我来说效率低下也是错误的 - 但我不知道更好的方法。是否有更好的方法,如果有,它是什么?
答案 0 :(得分:4)
条件变量允许您等待某个事件,并且具有一个条件变量的不同线程信号。
你可以有一个执行此操作的线程:
for (;;)
{
if (avail() > 0)
do_work();
else
pthread_cond_wait();
}
和另一个执行此操作的线程:
for (;;)
{
put_work();
pthread_cond_signal();
}
当然非常简化。 :)你需要查看如何正确使用它,由于竞争条件,使用条件变量有一些困难。
但是,如果您确定该线程将在非常短的时间内(以μs的顺序)阻塞,并且很少使用这样的自旋循环可能更有效。
答案 1 :(得分:3)
一般解决方案是使用POSIX信号量。这些不是pthread库的一部分,但与pthreads一样工作。
由于信号量是在大多数其他多线程API中提供的,因此它可能是一种可能更便携的通用技术;但是在这个例子中可能更合适的是 condition variable ,它允许线程在没有轮询的情况下挂起变量的条件值,这似乎完全你想要什么。
答案 2 :(得分:2)
条件变量是此问题的解决方案。您的代码可以很容易地修改为使用它们:
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
/* one thread, goal: block while mystruct->count == 0 */
void x(void *n) {
pthread_mutex_lock(&mymutex);
while (mystruct->count == 0)
pthread_cond_wait(&mycond, &mymutex);
printf("count no longer equals zero");
pthread_mutex_unlock(&mymutex);
pthread_exit((void*) 0)
}
/* another thread */
void y(void *n) {
sleep(10);
pthread_mutex_lock(&mymutex);
mystruct->count = 10;
pthread_cond_signal(&mycond);
pthread_mutex_unlock(&mymutex);
}
请注意,在对结果执行操作时,通常应该锁定互斥锁 - “消耗”事件或类似事件。这就是为什么我将pthread_mutex_unlock()
移到printf()
之后的一个点,即使在这个玩具案例中它并不重要。
(另外,在实际代码中,将互斥锁和条件变量放在mystruct
中)可能是有意义的。
答案 3 :(得分:1)
您可以使用barriers。
答案 4 :(得分:0)
您也可以使用semaphores来同步线程。