2012-11-26 100 views
2

我正在嘗試瞭解信號量和多線程。我正在使用的示例創建1到t個線程,每個線程指向下一個線程,最後一個線程指向第一個線程。這個程序允許每個線程順序地輪流,直到所有的線程都轉了n圈。那是程序結束的時候。唯一的問題是在tFunc函數中,我正在等待,直到它是一個特定的線程。我想知道如何使用信號燈,以便讓所有線程只有在輪到執行以提高效率時才進入睡眠狀態並喚醒線程。C++使用信號量而不是忙等待

int turn = 1; 
int counter = 0; 
int t, n; 

struct tData { 
     int me; 
     int next; 
}; 

void *tFunc(void *arg) { 
     struct tData *data; 
     data = (struct tData *) arg; 
     for (int i = 0; i < n; i++) { 
      while (turn != data->me) { 
     } 
     counter++; 
     turn = data->next; 
    } 
} 

int main (int argc, char *argv[]) { 
    t = atoi(argv[1]); 
    n = atoi(argv[2]); 
    struct tData td[t]; 
    pthread_t threads[t]; 
    int rc; 

    for (int i = 1; i <= t; i++) { 
     if (i == t) { 
      td[i].me = i; 
      td[i].next = 1; 
     } 
     else { 
      td[i].me = i; 
      td[i].next = i + 1; 
     } 
     rc = pthread_create(&threads[i], NULL, tFunc, (void *)&td[i]); 
     if (rc) { 
      cout << "Error: Unable to create thread, " << rc << endl; 
      exit(-1); 
     } 
    } 
    for (int i = 1; i <= t; i++) { 
     pthread_join(threads[i], NULL); 
    } 
    pthread_exit(NULL); 
} 
+1

'while(turn!= data-> me){}'?? – sje397

+0

C++數組基於零 - 'for(int i = 1; i <= t; i ++)'將超出數組邊界。 – sje397

+0

它只是循環直到輪到它。我只在網上找到了簡單的信號燈示例,並試圖實現它...但我認爲我需要多個信號量,現在我正在試圖圍繞如何實現它的過程中失去自己的頭腦。 – user1378863

回答

3

使用互斥鎖和條件變量。這是一個工作示例:

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

int turn = 1; 
int counter = 0; 
int t, n; 

struct tData { 
     int me; 
     int next; 
}; 

pthread_mutex_t mutex; 
pthread_cond_t cond; 

void *tFunc(void *arg) 
{ 
    struct tData *data; 
    data = (struct tData *) arg; 
    pthread_mutex_lock(&mutex); 
    for (int i = 0; i < n; i++) 
    { 
     while (turn != data->me) 
      pthread_cond_wait(&cond, &mutex); 
     counter++; 
     turn = data->next; 
     printf("%d goes (turn %d of %d), %d next\n", data->me, i+1, n, turn); 
     pthread_cond_broadcast(&cond); 
    } 
    pthread_mutex_unlock(&mutex); 
} 

int main (int argc, char *argv[]) { 
    t = atoi(argv[1]); 
    n = atoi(argv[2]); 
    struct tData td[t + 1]; 
    pthread_t threads[t + 1]; 
    int rc; 

    pthread_mutex_init(&mutex, NULL); 
    pthread_cond_init(&cond, NULL); 

    for (int i = 1; i <= t; i++) 
    { 
     td[i].me = i; 
     if (i == t) 
      td[i].next = 1; 
     else 
      td[i].next = i + 1; 

     rc = pthread_create(&threads[i], NULL, tFunc, (void *)&td[i]); 
     if (rc) 
     { 
      printf("Error: Unable to create thread: %d\n", rc); 
      exit(-1); 
     } 
    } 
    void *ret; 
    for (int i = 1; i <= t; i++) 
     pthread_join(threads[i], &ret); 
} 
0

使用N+1信號量。在啓動時,線程i等待信號量i。當喚醒它「需要轉and signals semaphore I + 1`

主線程派生的N,線程,信號旗語0並等待旗語N

僞代碼:。

sem s[N+1]; 

thread_proc (i): 
    repeat N: 
     wait (s [i]) 
     do_work() 
     signal (s [i+1]) 

main(): 
    for i in 0 .. N: 
    spawn (thread_proc, i) 

    repeat N:  
     signal (s [0]); 
     wait (s [N]); 
0

每個線程有一個信號量,每個線程wait在它的信號量上,如果sem_wait返回EINTR,則重試。一旦它完成了它的工作,把它的post加到下一個線程的信號量。 David的解決方案是一次只喚醒一個線程。

另請注意,由於您的信號量永遠不會超過一個值,因此您可以使用pthread_mutex_t