2012-12-27 93 views
0

我想確保我的sempahore做我期望做的事情,但我無法將它帶入一個或多個線程等待的狀態。我一次只需要3個線程就可以處理鏈表。信號量等待案例

代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <unistd.h> 
#include <math.h> 
#include <semaphore.h> 

struct dataBlock{ 
    struct node *root; 
    int listSize; 
    int forIndex; 
}; 

struct node { // std linked list node 
    int value; 
    int worker; 
    struct node *next; 
}; 

int limit = 5; 

sem_t sem; 

pthread_mutex_t mutp = PTHREAD_MUTEX_INITIALIZER; // mutex 
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; //condvar 

void *deleteDoneNodes(struct node *n){ 
    struct node *root = n; 
    struct node *it = root; 
    struct node *prev = NULL; 
    do{ 
     if(it->value == 1){ 
      struct node *next = it->next; 
      if (prev != NULL) { 
       prev->next = next; 
      } 
      if (it == root) { 
       root = next; 
      } 
      free(it); 
      it = next; 
     } 
     else { 
      prev = it; 
      it = it->next; 
     } 
    }while(it != NULL); 

    return root; 
} 

void * worker(void *data){ 
    //get list 
    int wFlag; 
    struct dataBlock *inData = (struct dataBlock *) data; 
    struct node *root = inData->root; 
    int forIndex = inData ->forIndex; 
    free(data); 


    while(1){ 

     if(sem_wait(&sem) != 0){ 
      printf(" > waiting... \n"); 
     } 
     // pthread_mutex_lock(&mutp); 
     struct node *it = root; 

     do{ 
      if(forIndex == it->worker){ 
       if(it->value > 2){ 
        while(it->value != 1) 
        it->value = sqrt(it->value); 
       } 
      } 
      else{ 
       // printf("Not sqrt-able node %d\n",it->value); 
      } 
      it = it->next; 
     }while(it != NULL); 

     // pthread_cond_signal(&condvar); 
     // pthread_mutex_unlock(&mutp); 
     sem_post(&sem); 
     // sleep(100); // "create" concurrancy envi. 
     pthread_exit(0);  
    } 

    return NULL; 
} 



int main(int argc, char *argv[]){ 
    if (argc != 3){ 
     printf("Programm must be called with \n NR of elements and NR of workers! \n "); 
     exit(1); 
    } 

    int i; 
    struct node *root; 
    struct node *iterator; 

//prepare list for task 
    int listSize = atoi(argv[1]); 
    int nrWorkers = atoi(argv[2]); 
    root = malloc(sizeof(struct node)); 

    root->value = rand() % 100; 
    root->worker = 0; 
    iterator = root; 

    for(i=1; i<listSize; i++){ 
     iterator->next = malloc(sizeof(struct node)); 
     iterator = iterator->next; 
     iterator->value = rand() % 100; 
     iterator->worker = i % nrWorkers; 
     printf("node #%d worker: %d value: %d\n", i, iterator->worker,iterator->value); 
    } 
    iterator->next = NULL; 
    printf("? List got populated\n"); 
// init semaphore > keeps max 3 threads working over the list 

    if(sem_init(&sem,0,3) < 0){ 
     perror("semaphore initilization"); 
     exit(0); 
    } 

// Create all threads to parse the link list 
    int ret;  
    pthread_mutex_init(&mutp,NULL); 

    pthread_t w_thread; 
    pthread_t* w_threads = malloc(nrWorkers * sizeof(w_thread)); 

    for(i=0; i < nrWorkers; i++){   
     struct dataBlock *data = malloc(sizeof(struct dataBlock)); 
     data->root = root; 
     data->listSize = listSize; 
     data->forIndex = i; 
     ret = pthread_create (&w_threads[i], NULL, worker, (void *) data); 
     if(ret) { 
      perror("Thread creation fail"); 
      exit(2);  
     } 
    } 

    deleteDoneNodes(root); 

    int join; 
    for (i = 0; i < nrWorkers; i++){ 
     join = pthread_join(w_threads[i],NULL); 
    } 

    iterator = root; 
    for (i = 0; i < listSize; i++){ 
     printf("val: %d worker: %d _ \n", iterator->value, iterator->worker); 
     iterator = iterator->next; 
    } 

    free(root); 
    free(iterator); 
    sem_destroy(&sem); 
    return 0; 
} 

終端〜> ./s 16 16

node #1 worker: 1 value: 86 
node #2 worker: 2 value: 77 
node #3 worker: 3 value: 15 
node #4 worker: 4 value: 93 
node #5 worker: 5 value: 35 
node #6 worker: 6 value: 86 
node #7 worker: 7 value: 92 
node #8 worker: 8 value: 49 
node #9 worker: 9 value: 21 
node #10 worker: 10 value: 62 
node #11 worker: 11 value: 27 
node #12 worker: 12 value: 90 
node #13 worker: 13 value: 59 
node #14 worker: 14 value: 63 
node #15 worker: 15 value: 26 
? List got populated 
val: 1 worker: 0 _ 
val: 1 worker: 1 _ 
val: 1 worker: 2 _ 
val: 1 worker: 3 _ 
val: 1 worker: 4 _ 
val: 1 worker: 5 _ 
val: 1 worker: 6 _ 
val: 1 worker: 7 _ 
val: 1 worker: 8 _ 
val: 1 worker: 9 _ 
val: 1 worker: 10 _ 
val: 1 worker: 11 _ 
val: 1 worker: 12 _ 
val: 1 worker: 13 _ 
val: 1 worker: 14 _ 
val: 1 worker: 15 _ 
+0

你希望發生什麼,但沒有?你是否嘗試在'sem_wait()'/'sem_post()'塊中放置註釋的sleep()'*而不是外部? – Flavio

+0

請勿動態重新初始化您的互斥鎖。靜態初始化是完全足夠的。 w_thread有什麼用?只是計算'pthread_t'類型的'sizeof'?所有這些都表明,你應該先自己去完成你的代碼,找出一個具體的問題,把它歸結爲可重現的東西,然後再回來。 SO不適用於代碼審查。 –

+0

@flavo爲什麼我會那樣做?!我需要線程等待,在做任何事之前 –

回答

0

我可以在代碼中看到一些潛在的錯誤。

首先,我認爲你的評論區是所有的節點,所以你應該保護所有的訪問互斥。在你的工人你沒有這樣做。

儘管如此,您的信號量應該可以工作:初始化爲3,線程函數開始時使用sem_wait,結束時使用sem_post。

所以,我能想到的最大可能的問題是你的deletenodes函數。 不要忘記,main也是一個線程,並且由於在連接之前刪除節點,並且發送到線程的數據是使用指針構造的,所以如果在處理數據之前所有線程都丟失了處理器,並且你的主線程得到處理器,它會清理所有的數據類型的節點,並在最好的情況下傳遞給工作線程,過時的,空的,空的。 發生這種情況,就像我說過的,因爲您通過指針/引用而不是通過複製將值傳遞給數據。我可以看到兩種可能的解決方案:或者在聯接之後調用刪除節點(將主線程狀態設置爲阻塞狀態,斷言您刪除節點的呼叫發生在所有線程結束之後),或者通過複製將值傳遞給數據在我看來,會給你更多的工作)。

希望這會有所幫助。

0

使用從油嘴線程池「http://developer.gnome.org/glib/stable/glib -Thread-Pools.html「

+0

我認爲用戶正在尋找理解水平來讓發佈的代碼工作,而不是完全解決問題的庫。 –