как избежать опроса в pthreads - PullRequest
4 голосов
/ 05 июня 2011

У меня есть код, который в настоящее время выглядит следующим образом (упрощенно)

/* 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 ]

4 голосов
/ 05 июня 2011

Переменные условия позволяют вам ожидать определенного события и иметь другой поток, который сигнализирует эту переменную условия.

У вас может быть тема, которая делает это:

for (;;)
{
   if (avail() > 0)
      do_work();
   else
      pthread_cond_wait();
}

и другой поток, который делает это:

for (;;)
{
   put_work();
   pthread_cond_signal();
}

Очень упрощенно, конечно. :) Вам нужно будет посмотреть, как правильно его использовать, есть некоторые трудности при работе с переменными условия из-за условий гонки.

Однако, если вы уверены, что поток будет блокироваться в течение очень короткого времени (порядка мкс) и редко, использование подобной спиновой петли, вероятно, будет более эффективным.

3 голосов
/ 05 июня 2011

Общее решение - использовать семафор POSIX. Они не являются частью библиотеки pthread, но работают с pthreads точно так же.

Поскольку семафоры предоставляются в большинстве других многопоточных API, это общая методика, которая может быть применена, возможно, более переносимо; однако, возможно, более уместным в этом случае является условная переменная , которая позволяет потоку ожидать условного значения переменной без опроса, который, кажется, равен точно что вы хотите.

2 голосов
/ 06 июня 2011

Переменные условия являются решением этой проблемы.Ваш код может быть довольно легко изменен, чтобы использовать их:

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).

1 голос
/ 05 июня 2011

Вы можете использовать барьеры .

0 голосов
/ 05 июня 2011

Вы также можете использовать семафоры для синхронизации потоков.

...