如何避免pthreads中的轮询

时间:2011-06-05 14:16:11

标签: c multithreading pthreads posix

我有一些目前看起来像这样的代码(简化)

/* 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);
}

这对我来说效率低下也是错误的 - 但我不知道更好的方法。是否有更好的方法,如果有,它是什么?

5 个答案:

答案 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来同步线程。