首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >信号量等待情况

信号量等待情况
EN

Stack Overflow用户
提问于 2012-12-27 22:04:38
回答 2查看 553关注 0票数 0

我想确保我的sempahore能做我期望做的事情,但我不能把它带到一个或多个线程等待的状态。我需要只有3个线程在同一时间能够在链表上工作。

代码:

代码语言:javascript
复制
#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;
}

terminal~>。/s 16 16

代码语言:javascript
复制
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 _  
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-12-28 01:07:05

我可以在你的代码中看到一些潜在的bug。

首先,我认为你的关键区域是所有的节点,所以你应该用一个互斥锁来保护所有的访问。在你的worker中,你没有做到这一点。

不过,您的信号量应该可以工作:用3初始化,在线程函数的开头用sem_wait,在线程函数的末尾用sem_post。

所以,我能想到的最大的问题就是你的deletenodes函数。不要忘记main也是一个线程,因为在连接之前要删除节点,并且发送到线程的数据是用指针构造的,如果所有线程在处理数据之前都失去了处理器,而主线程获得了处理器,那么它将清除所有构成数据类型的节点,传递给工作线程,在最好的情况下,这些节点是过时的、空的、null。这种情况会发生,就像我说的,因为你通过指针/引用而不是通过复制将值传递给数据。我可以看到两种可能的解决方案:一种是在连接之后调用删除节点(这会将主线程状态设置为blocked,断言删除节点的调用在所有线程结束后发生);另一种是通过复制将值传递给数据(在我看来,这将给您提供更多的工作)。

希望这能有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2012-12-27 22:21:42

使用glib "http://developer.gnome.org/glib/stable/glib-Thread-Pools.html“中的线程池

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14055933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档