2015-02-15 3 views
0

Я новичок в потоках и, похоже, имею проблему с синхронизацией. Когда я запускаю свой код, мой выход ...Pthreads and signals C++

Полученные данные!
Данные обработаны!

, а затем он просто висит. Я предполагаю, что использую wait и сигнал неправильно. Помощь будет принята с благодарностью.

#include <string.h> 
#include <pthread.h> 
#include <stdio.h> 
#include <unistd.h> 

char buffer [100]; 
pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER; 

void* threadFunc(void *proc){ 
    if((int)proc == 0){ 
     pthread_mutex_lock(&buffer_mutex); 
     sprintf(buffer, "Data received!\n"); 
     printf("%s", buffer); 
     pthread_cond_signal(&buffer_cond); 
     pthread_mutex_unlock(&buffer_mutex); 
    } 
    else if((int)proc == 1){ 
     pthread_mutex_lock(&buffer_mutex); 
     pthread_cond_wait(&buffer_cond, &buffer_mutex); 
     sprintf(buffer, "Data processed!\n"); 
     printf("%s", buffer); 
     pthread_cond_signal(&buffer_cond); 
     pthread_mutex_unlock(&buffer_mutex); 
    } 
    else{ 
     sleep(1); 
     pthread_mutex_lock(&buffer_mutex); 
     pthread_cond_wait(&buffer_cond, &buffer_mutex); 
     sprintf(buffer, "Data sent!\n"); 
     printf("%s", buffer); 
     pthread_mutex_unlock(&buffer_mutex); 
    } 

    return(NULL); 
} 

int main() 
{ 
    pthread_t threads[3]; 

    for(int i = 0; i < 3; i++){ 
     pthread_create(&threads[i], NULL, threadFunc, (void *) i); 
    } 

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

    return 0; 
} 

ответ

2

Переменная состояние почти бесполезен без предиката, условное состояние, которое диктует , что изменилось. Переменная условия - это нечто большее, чем механизм сигнализации, объявляющий, что «что-то» может измениться, но вам все равно нужно управлять «чем». И этот мьютекс защищает это «что».

Например:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <string.h> 
#include <pthread.h> 

char buffer [100]; 
int state = 0; 

pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER; 

void* threadFunc(void *proc) 
{ 
    intptr_t iptr = (intptr_t)proc; 
    pthread_mutex_lock(&buffer_mutex); 

    switch(iptr) 
    { 
     case 0: 
     { 
      while (state != 1) // 1 means data available 
       pthread_cond_wait(&buffer_cond, &buffer_mutex); 

      // mutex is locked. access predicate data 
      printf("Data received: %s\n", buffer); 
      state = 2; // advance state 
      pthread_mutex_unlock(&buffer_mutex); 
      pthread_cond_broadcast(&buffer_cond); 
     } 
     break; 

     case 1: 
     { 
      while (state != 2) 
       pthread_cond_wait(&buffer_cond, &buffer_mutex); 

      // mutex is locked. access predicate data 
      printf("Data processed: %s\n", buffer); 
      pthread_mutex_unlock(&buffer_mutex); 
     } 
     break; 

     default: 
     { 
      // setup initial send-state 
      printf("Data sent: %s\n", buffer); 
      state = 1; 
      pthread_mutex_unlock(&buffer_mutex); 
      pthread_cond_broadcast(&buffer_cond); 
     } 
    } 
    return NULL; 
} 

int main() 
{ 
    pthread_t threads[3]; 
    intptr_t i = 0; 

    strcpy(buffer, "Some message"); 

    for(i = 0; i < 3; i++){ 
     pthread_create(&threads[i], NULL, threadFunc, (void *) i); 
    } 

    for(i = 0; i < 3; i++) 
     pthread_join(threads[i], NULL); 

    return 0; 
} 

Выход

Data sent: Some message 
Data received: Some message 
Data processed: Some message 

Это просто запускает три темы. Один (id = 0) будет ждать, пока состояние станет 1, затем продолжит работу над объявлением того, что произошло, продвижением состояния и сигнализацией о состоянии. Второй (id = 1) ждет этого состояния, выполняет свою работу аналогично, а затем просто выходит, поскольку больше ничего не нужно делать. Третий (id = 2) - тот, который запускает процесс, затем бесшумно заканчивается.

Обратите внимание, что данные предиката (состояние) ни в коем случае не изменяются или не проверены, не находясь под защитой мьютекса на любом потоке, выполняющем указанную проверку/изменение.

Три временных графика с состоянием mutex-latch и какая нить владеет им, будут говорить томами в понимании того, как это работает, и я настоятельно советую вам получить карандаш и бумагу, чтобы помочь в этом отношении.

Удачи.