Question

J'ai deux threads, j'utilise des pthreads C sur Linux. L'un d'eux écrit des données et l'autre les lit. J'utilise une variable pour permettre au thread de lecture quand est autorisé à lire et celui d'écrire quand est autorisé. Le mutex s'applique donc à cette variable booléenne appelée "newData". Ma question est la suivante: dois-je verrouiller / déverrouiller le mutex autour des accès situés à l'intérieur de l'option "if" & état? Les deux méthodes fonctionnent, mais je pense que tout simplement parce que les chances de chevauchement d'une écriture / lecture sur une variable sont très rares. Je montre les deux alternatives pour mieux expliquer ma question:

Sujet 1:

pthread_mutex_lock( &lattice_mutex );
if (!newData) {
    pthread_mutex_unlock( &lattice_mutex );
    uchar *lattice_pos = lattice;
    int i;
    for(i=0; i<size; i++) {
        *lattice_pos = rand()%CHAR_MAX;
        lattice_pos++;
    }
    pthread_mutex_lock( &lattice_mutex );
    newData = TRUE;
    pthread_mutex_unlock( &lattice_mutex );
} else {
    pthread_mutex_unlock( &lattice_mutex );
}

Sujet 2:

pthread_mutex_lock( &lattice_mutex );
if(newData) {
    pthread_mutex_unlock( &lattice_mutex );
    renderUpdate();
    pthread_mutex_lock( &lattice_mutex );
    newData = FALSE;
    pthread_mutex_unlock( &lattice_mutex );
} else {
    pthread_mutex_unlock( &lattice_mutex );
}

Deuxième version, qui fonctionne mais je ne sais pas si elle est correcte:

Sujet 1:

if (!newData) {
    uchar *lattice_pos = lattice;
    int i;
    for(i=0; i<size; i++) {
        *lattice_pos = rand()%CHAR_MAX;
        lattice_pos++;
    }
    pthread_mutex_lock( &lattice_mutex );
    newData = TRUE;
    pthread_mutex_unlock( &lattice_mutex );
}

Sujet 2:

if(newData) {
    renderUpdate();
    pthread_mutex_lock( &lattice_mutex );
    newData = FALSE;
    pthread_mutex_unlock( &lattice_mutex );
}
Était-ce utile?

La solution

Ceci est dérivé de votre première version - c'est un peu plus simple.

Sujet 1: écrivain

pthread_mutex_lock(&lattice_mutex);
if (!newData) {
    pthread_mutex_unlock(&lattice_mutex);  // Omit?
    uchar *lattice_pos = lattice;
    int i;
    for (i = 0; i < size; i++)
        *lattice_pos++ = rand() % CHAR_MAX;
    pthread_mutex_lock(&lattice_mutex);   // Omit?
    newData = TRUE;
}
pthread_mutex_unlock(&lattice_mutex);

Fil 2: lecteur

pthread_mutex_lock(&lattice_mutex);
if (newData) {
    pthread_mutex_unlock(&lattice_mutex);   // Omit?
    renderUpdate();
    pthread_mutex_lock(&lattice_mutex);     // Omit?
    newData = FALSE;
}
pthread_mutex_unlock(&lattice_mutex);

Cela dépend de la manière dont les informations de réseau sont censées être utilisées, mais étant donné le nom du mutex, je pense que vous devriez le garder verrouillé pendant que vous modifiez le réseau, d'où les deux paires de lignes marquées "Omettre?" devrais être retiré. Sinon, le réseau n'est pas protégé contre les accès concurrents.

Ajouté: Je pense que la deuxième version est erronée - elle ne protège pas correctement le réseau.

Autres conseils

La première version est correcte, vous avez besoin du mutex à la fois en écriture et en lecture.

Cependant, autant que je sache, presque toutes les architectures disposent d'un simple accès en lecture et en écriture à une unité de données (par exemple, int) atomique. Cependant, notez que sur les architectures avec un ordre de mémoire faible, vous pouvez rencontrer des problèmes tels que l'affichage de la commande "tampon plein". drapeau sur true avant que le tampon ne contienne réellement les données.

Notez que le code n'est probablement pas le meilleur que vous puissiez faire, car il ne dort jamais (utilise l'attente). Si vous souhaitez attendre les données dans l'un des threads, vous devez utiliser une variable de condition avec le mutex.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top