2017-05-25 7 views
0

Ci-dessous est mon code dans lequel deux variables sont mises à jour lors du rappel qui est appelé toutes les 50 ms. Il y a aussi un fil de lecture qui se réveille toutes les 50ms et lit les variables. Après avoir passé par this, j'ai deviné qu'il y aura des cas où le thread qui lit se réveillera juste quand un rappel est reçu et puisque je ne verrouille pas le même mutex pendant la lecture et l'écriture, dans ce cas il sera entraîner une lecture incohérente de la mémoire. Cependant, lorsque je l'exécute, ce scénario ne se produit jamais. Est-ce que je ne l'ai pas utilisé assez longtemps ou y a-t-il une erreur dans ma compréhension?Écriture en lecture simultanée

recursive_mutex mutex1 
recursive_mutex mutex2 
var1, var2 

//called every 50ms 
onUpdateListener() { 
    lock(mutex1) 
    update var1 
    update var2 
} 

VarReaderThread::readVar() { 
    sleep(50) 
    while(true) { 
     { 
     lock(mutex2) 
     read var1 
     read var2 
     sleep(50) 
     } 
    } 
} 
+0

La 'portée' de vos mutex n'est pas claire. –

+1

Pourquoi utiliser ces mutex? Y a-t-il d'autres codes accédant aux vars? Parce que dans ce scénario, ils sont totalement inutiles. –

+0

Vous ne devriez pas écrire et lire en même temps ou vous pourriez rencontrer un état incohérent (condition de concurrence). Vous ne devriez pas écrire et écrire en même temps, même si la lecture et la lecture peuvent être effectuées simultanément. L'écriture ne se mélange pas. L'utilisation de verrous séparés pour la lecture et l'écriture n'aidera pas. comme le suggère @HenkHolterman dans ce code, ces mutex ne font rien. – Persixty

Répondre

0

Une course de données se produit lorsque deux ou plusieurs fils ont accès à des données partagées dans lesquels au moins un est une opération d'écriture dans laquelle un ou plusieurs fils peuvent rencontrer un état incohérent.

Le code fourni a deux mutex, un pour la lecture et un pour l'écriture. Cela n'exclut en aucun cas un thread de lire les données partagées (var1, var2 dans l'exemple) alors qu'un autre leur écrit ou plus précisément après avoir commencé à écrire sur l'un d'entre eux et avant d'avoir fini d'écrire dans l'autre dans une situation où cet état intermédiaire serait considéré comme un état incohérent dans les paramètres de la logique du code et son but. Un mutex est requis pour que la lecture et l'écriture soient exclusives. En aparté, on ne sait pas pourquoi un mutex récursif a été déclaré. Cela ne serait nécessaire que si un thread donné rencontrait un code l'obligeant à obtenir un mutex qu'il détient déjà. C'est mieux de concevoir et de coder cette situation là où c'est possible.

explicite unlock mesures ont été introduites qui peuvent ou peuvent ne pas être explicitement en fonction du modèle de codage (requis en C, utiliser std::lock_guard en C++ ou synchronized ou finally en Java, etc.).

Une condition a été introduite pour indiquer une condition de terminaison appropriée. while(true) est une mauvaise pratique à moins qu'une autre condition ne le termine gracieusement.

Des modèles plus sophistiqués peuvent utiliser un 'mutex partagé' dans lequel plus d'un thread peut le maintenir en mode 'read' mais un seul si on le maintient en mode 'write'. Cela peut nécessiter ou non une certaine signalisation pour s'assurer que 'write' n'entrera pas dans un live-lock où de nombreux lecteurs bloquent indéfiniment l'accès 'write'.

mutex mutex_v1_v2 //The mutex controlling shared state var1, var2. 
var1, var2 

//called every 50ms 
onUpdateListener() { 
    lock(mutex_v1_v2) 
    update var1 
    update var2 
    unlock(mutex_v1_v2) 
} 

VarReaderThread::readVar() { 
    sleep(50) 
    while(!finished) { 
     lock(mutex_v1_v2) 
     read var1 
     read var2 
     unlock(mutex_v1_v2) 
     sleep(50) //V. V. important to sleep not holding the mutex! 
    } 
}