2015-03-25 2 views
1

Я только начал изучать переменную условия pthread. Но ниже код работает не так, как ожидалось.Зачем изменять переменную pthread_condition?

#include<iostream> 
#include<pthread.h> 

using namespace std; 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t count_threshold_cv = PTHREAD_COND_INITIALIZER; 
int count=0; 


void *inc_func(void *arg) 
{ 
    pthread_mutex_lock(&mutex); 
    int c; 

    while(1) 
    { 
     cin>>c; 
     if(c==8){ 
      pthread_cond_signal(&count_threshold_cv);break;} 
    } 

    cout<<"inc count reached 8"<<endl; 
    pthread_mutex_unlock(&mutex); 

} 

void *watch(void *arg) 
{ 
    pthread_mutex_lock(&mutex); 
    while(1){ 
     pthread_cond_wait(&count_threshold_cv,&mutex); 
     break; 
    } 
    cout<<"This executed"<<endl; 
    pthread_mutex_unlock(&mutex); 
} 

int main() 
{ 
    pthread_t id[26]; 
    pthread_create(&id[0],NULL,inc_func,NULL); 
    pthread_create(&id[1],NULL,watch,NULL); 

    int i; 
    for(i=0;i<2;i++) 
    { 
     pthread_join(id[i],NULL); 
    } 

} 

, когда вход 8 этот код получает повешен на «вкл COUNT достигло 8 Я не могу понять Где мое понимание неправильно

ответ

2

Важно то, что pthread_cond_signal разблокирует хотя бы один из потоков, которые блокируются этой переменной условия (что означает, что в настоящее время блокируется при вызове pthread_cond_wait по той же переменной условия). Если в тот момент, когда один поток вызывает pthread_cond_signal, нет другого потока, ожидающего этого условия, тогда в принципе ничего не происходит.

Имея это в виду, поток вашей программы что-то вроде этого:

  • создать и запустить первую нитку;
  • первая нить вызывает inc_func(), которая блокирует мьютекс перед чем-либо еще;
  • inc_func() продолжает ждать ввода номера 8, сохраняя мьютекс заблокированным все это время;
  • когда-то во время этого, но в большинстве случаев, вероятно, после того, как inc_func удалось заблокировать мьютексы, создается второй поток;
  • второй поток также пытается заблокировать мьютекс прямо в начале функции и заблокирован, поскольку первый поток уже заблокирован;
  • В какой-то момент вы вводите 8, и условие получает сигнал от потока 1; нить 2 не ждет этого условия, поэтому он остается заблокированным, пытаясь заблокировать мьютекс;
  • первая нить окончательно освобождает мьютекс, поэтому поток 2 блокирует его, а затем блокирует по pthread_cond_wait.

На этом этапе нить 1 уже завершена, нить 2 заблокирована, ожидая, что условие будет сигнализировано, и основной поток ждет его завершения. Больше никто не должен сигнализировать об этом состоянии, поэтому у вас есть зависание.

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

1

Своп нить в последовательность выполнения:.?

pthread_create(&id[1],NULL,watch,NULL); 
pthread_create(&id[0],NULL,inc_func,NULL); 

Если вы запускаете thread0 как первый, thread1 никогда не попадает мимо синхронизирующей блокировки, поэтому он не начинает ждать. чем thread0 концов, и только затем thread1 выполняет pthread_cond_wait(), но нет нитки, чтобы сделать signal.

Если вы сначала запустите thread1, он доберется до ожидающей части.

3

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

условие, как представляется c == 8 (так как это то, что сигнал), так что вам нужно будет сделать c переменную глобальной, так что она распределяется между нитями, а затем изменить watch нить сделать:

void *watch(void *arg) 
{ 
    pthread_mutex_lock(&mutex); 
    while (c != 8) { 
     pthread_cond_wait(&count_threshold_cv, &mutex); 
    } 
    cout<<"This executed"<<endl; 
    pthread_mutex_unlock(&mutex); 

    return 0; 
} 

Теперь не имеет значения, какой поток выполняется первым: ваш код правильный в любом случае. Это правильный способ использовать условные переменные: в общем, официант должен сделать:

pthread_mutex_lock(&mutex); 

while (!condition) 
    pthread_cond_wait(&cond, &mutex); 

/* ... */ 

и сигнальщик должны сделать:

pthread_mutex_lock(&mutex); 

/* ... something that potentially makes condition true ... */ 

pthread_cond_broadcast(&cond); 
pthread_mutex_unlock(&mutex); 
Смежные вопросы