2012-12-27 94 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

我认为用户正在寻找理解水平来让发布的代码工作,而不是完全解决问题的库。 –