/ / Синхронизиране на нишки, използващи два буфера и два шлюзове за mutex: C - c, multithreading, синхронизация, блокиране, mutex

Синхронизация на нишката, използваща два буфера и два шлюзове за mutex: C-c, multithreading, синхронизация, блокиране, mutex

Имам проблеми с типичната Производител и потребителски проблем, имам функция на производителя, че основната нишкаще работи с потребителска функция, за която се обаждат множество нишки; вземане на елементи от един буфер и поставянето им в друг, използвайки безопасна заключваща система mutex. Им мисля, че имам нужда от две mutex брави за управление на двата буфера, но аз съм тичане в крайна линия.

КОД:

    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 = %dnn", 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 %sn", 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) и да добавяте елементи към него, ако стигна до точка, където няма повече елементи, тогава искам да освободя тази заключалка, така че моят потребител може да вземе тези елементи от буфер и да ги поставите в outputq, по някаква причина изглежда, че основната нишка не чака и освобождаване на ключалката?

Отговори:

0 за отговор № 1

Виждам тук няколко проблема. Първият е в производствената част с (loop sptr = rule-> deps; sptr! = NULL; sptr = sptr-> next). Вътре в този цикъл заключвате mut_output mutex, така че може да бъде заключен многократно (ако е рекурсивен mutex), но е отключен само веднъж, когато цикълът завърши.

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