2010-06-15 9 views
2

J'ai un problème avec les mutex (pthread_mutex sous Linux) où si un thread verrouille à nouveau un mutex après l'avoir déverrouillé, un autre thread ne réussit pas à obtenir un verrou. J'ai attaché le code de test où un mutex est créé, avec deux threads qui dans une boucle sans fin verrouillent le mutex, dorment pendant un moment et le déverrouillent encore. La sortie que je m'attends à voir est des messages "vivants" des deux threads, un de chaque (par exemple 121212121212. Cependant, ce que je reçois est que les threads obtient la majorité des verrous (par exemple 111111222222222111111111 ou simplement 1111111111111 ...).Verrouillage permanent du mutex entraînant un blocage?

Si j'ajoute un usleep (1) après le déverrouillage, tout fonctionne comme prévu.Il semble que lorsque le thread passe à SLEEP l'autre thread obtient son verrou - mais ce n'est pas la façon dont je l'attendais, comme l'autre thread J'ai déjà appelé pthread_mutex_lock, je suppose que c'est la façon dont cela est implémenté, en ce sens que le thread actice a la priorité, mais il crée un problème dans ce cas particulier (y a-t-il un moyen de l'empêcher? une sorte de signalisation) ou où est mon erreur en compréhension?

#include <pthread.h> 
#include <stdio.h> 

#include <string.h> 
#include <sys/time.h> 
#include <unistd.h> 

pthread_mutex_t mutex; 

void* threadFunction(void *id) { 
int count=0; 

while(true) { 
    pthread_mutex_lock(&mutex); 
    usleep(50*1000); 
    pthread_mutex_unlock(&mutex); 
    // usleep(1); 

    ++count; 
    if (count % 10 == 0) { 
    printf("Thread %d alive\n", *(int*)id); 
    count = 0; 
    } 
} 

return 0; 
} 

int main() { 
// create one mutex 
pthread_mutexattr_t attr; 
pthread_mutexattr_init(&attr); 
pthread_mutex_init(&mutex, &attr); 

// create two threads 
pthread_t thread1; 
pthread_t thread2; 

pthread_attr_t attributes; 
pthread_attr_init(&attributes); 

int id1 = 1, id2 = 2; 
pthread_create(&thread1, &attributes, &threadFunction, &id1); 
pthread_create(&thread2, &attributes, &threadFunction, &id2); 

pthread_attr_destroy(&attributes); 

sleep(1000); 
return 0; 
} 

Répondre

2

Vous vous méprenez sur le fonctionnement des mutex (au moins dans le cadre de votre implémentation particulière). La sortie d'un mutex ne passe pas automatiquement à un autre thread qui l'attend.

Généralement, les threads continuent à fonctionner jusqu'à ce qu'ils doivent attendre une ressource ou qu'ils utilisent leur quantum (tranche de temps). Lorsqu'il n'y a pas de conflit de ressources et que tous les threads ont la même priorité, l'algorithme d'ordonnancement le plus juste est de donner à chacun une tranche de temps égale avant l'échange. C'est parce que l'opération d'échange elle-même prend du temps, donc vous ne voulez pas trop le faire (par rapport au vrai travail effectué par les threads.)

Si vous voulez alterner entre les threads, vous avez besoin de quelque chose de plus déterministe que mutex, comme un ensemble de variables de condition:

+0

J'espérais que l'appel de verrouillage de l'autre thread aurait été enregistré et que le verrou du thread en cours d'exécution n'aboutisse pas (c'est-à-dire les mutex en file d'attente). Comme il s'agit d'un cas de test artificiel et qu'il ne se passe pas réellement dans mon application, je m'en tiendrai à cela, mais gardez votre réponse à l'esprit si ce problème venait à se reproduire. – Daniel

1

Ceci est interblocage pas, il est même pas livelock il est simplement un cas de Si cela est essentiel pour vous manque équité, vous devez utiliser des primitives.. assurer la non-famine, par exemple un mutex en file d'attente

0

Lorsque le premier thread déverrouille le mutex, il y aura bien sûr un certain délai avant que ce changement ne soit ava utilisable sur l'autre thread. Cela est probablement plus long que le premier thread à verrouiller le mutex, car il n'a pas à attendre cette fois.