Синхронизация потоков с использованием двух буферов и двух блокировок мьютекса: C - PullRequest
0 голосов
/ 07 апреля 2011

У меня проблема с типичной проблемой производителя и потребителя , у меня есть функция производителя, с которой будет работать основной поток, и функция потребителя, которую вызывают несколько потоков; брать элементы из одного буфера и помещать их в другой с помощью безопасной блокировки мьютекса. Я думаю, мне нужны две блокировки мьютекса, чтобы управлять обоими буферами, но я работаю в конечном цикле.

КОД:

    int add_rule_input(rule_t* rule, rule_node_t* list) {
    int i, error;   
str_node_t* sptr;
rule_node_t* rptr;


if(error = pthread_mutex_lock(&mut_access)){
        return error;
}

error = pthread_cond_wait(&buffer_empty, &mut_access);

//first check to see if dependencies are in the output queue    
for(sptr = rule->deps; sptr != NULL; sptr = sptr->next){
        dep_count++; 
pthread_mutex_lock(&mut_output);
for(i = 0; i < ArraySize; i++){

    if(outputQ[i] != NULL){

if(strcmp(sptr->str, outputQ[i]) == 0){
    array_count++;
                break; // go the next rule in the output q
        }else{
            //means the first element in our array did not have the current
                continue;       
            }   
        }else{
error = pthread_cond_wait(&buffer_empty, &mut_output);
            break;
}
    }
}       
pthread_mutex_unlock(&mut_output);

inputQ[bufin] = rule->target;//the element wherever the current place is
printf("buffer got %s buffin = %d\n\n", inputQ[bufin], bufin);
bufin = (bufin + 1);
totalitems++; 
pthread_cond_signal(&buffer_full);

return pthread_mutex_unlock(&mut_access);

}

Моя потребительская функция, которая обращается к другому выходному буферу

static void *consumer(void *arg){

rule_node_t* lptr = (rule_node_t*)arg;
str_node_t* dptr;   
 int error, i, j;
int test1 = 0;
//grab lock to read the input queue
    if(error = pthread_mutex_lock(&mut_access))
    return error;


if(error){

        pthread_mutex_unlock(&mut_access);
        return error;
    }


 // loop through all our rules
    while(lptr != NULL){

// loop through each rules dependencies to compare with item in the input queue
    for(dptr = lptr->rule->deps; dptr != NULL; dptr = dptr->next){
    // now loop through our input q if we get the lock  
        for(j = 0; j > ArraySize; j++){

              if(inputQ[j] != NULL){

        if(strcmp(dptr->str, inputQ[j]) == 0){
            fake_exec(lptr->rule); // if we get here there is a rule that needs to be executed
            pthread_mutex_lock(&mut_output);
            //update the output queue and release the lock

         if(outputQ[bufout] == NULL){
    outputQ[bufout]= lptr->rule->target;
    bufout = (bufout + 1);
    printf("bufout has %s\n", outputQ[bufout]);

    }
    pthread_mutex_unlock(&mut_output); 
}                           
    }   
    }
error = pthread_cond_wait(&buffer_full, &mut_access);   
}
    lptr = lptr->next;
}
 pthread_cond_signal(&buffer_empty);
pthread_mutex_unlock(&mut_access);  


 }

ВОПРОСЫ: 1} Я попытался сначала захватить блокировку для моего первого буфера (inputq) и добавить в нее элементы, если я достигну точки, где больше нет элементов, то я хочу снять эту блокировку, чтобы мой потребитель мог взять эти элементы из буферизировать и помещать их в выходной q, почему-то кажется, что основной поток не ждет и не снимает блокировку?

1 Ответ

1 голос
/ 07 апреля 2011

Я вижу здесь несколько проблем.Первый находится в части производителя с циклом for (sptr = rule-> deps; sptr! = NULL; sptr = sptr-> next).Внутри этого цикла вы блокируете мьютекс mut_output, поэтому его можно заблокировать несколько раз (если он является рекурсивным мьютексом), но разблокируется только один раз, когда цикл заканчивается.

Другая проблема связана с pthread_cond_wait (& buffer_empty, & mut_output) ;.Давайте представим, что это ожидание в продюсере обедено.Когда он запускается, мьютекс mut_access блокируется производителем, а теперь, когда потребитель выполняется, он пытается получить mut_access, но не может, потому что он уже заблокирован, так что потребитель также ждет, и более новая часть достижения, когда он сигнализирует условной переменной buffer_empty, чтобы разблокировать производителя,Вероятно, в этом pthread_cond_wait вы хотели передать mut_access вместо mut_output.

...