Introduction à la programmation concurrente Verrous et sémaphores Yann Thoma Reconfigurable and Embedded Digital Systems Institute Haute Ecole d’Ingénierie et de Gestion du Canton de Vaud This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License Février 2017 Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 1 / 39
42
Embed
Introduction à la programmation concurrente · Dans le cadre du cours, nous laisserons timeout à 0. ... Signalisation voidrelease(intn=1); Incrémente (débloque) le sémaphore
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Introduction à la programmation concurrenteVerrous et sémaphores
Yann Thoma
Reconfigurable and Embedded Digital Systems InstituteHaute Ecole d’Ingénierie et de Gestion du Canton de Vaud
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
Février 2017
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 1 / 39
Verrous Introduction
Verrous
L’attente active a un énorme désavantage:Réquisition du processeur
Solution: les verrousLe verrou
est une variable booléennepossède une liste d’attenteest manipulé par deux opérations atomiques:
Verrouille(v)Deverrouille(v)
En anglais: mutex, pour mutual exclusion
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 2 / 39
Verrous Introduction
Verrous
Pseudocode des deux opérations
void Verrouille(verrou v){
if (v)v = false;
elsesuspendre la tâche appelante dans la file associée à v
}
void Déverrouille(verrou v){
if (la file associée à v != vide)débloquer une tâche en attente dans file
elsev = true;
}
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 3 / 39
Verrous Introduction
Verrous - Points importants
Un mutex possède un "propriétaire" : le thread ayant obtenu le verrou estle propriétaire du mutex jusqu’à ce qu’il le déverrouille :⇒ le thread ayant verrouillé le mutex est responsable de le déverrouiller
(relâcher); un thread ne peut pas déverrouiller un mutex déjà verrouillé parun autre thread.
Les fonctions lock et unlock sont atomiques !
Verrouiller un mutex déjà verrouillé bloque le thread appelant⇒deadlock assuré si un même thread verrouille un mutex de façonconsécutive (sauf pour les mutex récursifs).
Déverrouiller un mutex plusieurs fois n’a pas d’effet⇒ pas de"mémoire" du nombre de fois qu’un mutex a été déverrouillé (sauf pourles mutex récursifs).
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 4 / 39
Verrous Introduction
Utilisation des verrous: Section critique
Une section critique peut être protégée par un verrou
global = global + 1;std::cout << "I got the mutex" << std::endl;mutex.unlock();
}else
std::cout << "I cannot get the mutex" << std::endl;}
}};
int main(void) {MyThread tache1, tache2;tache1.start();tache2.start();tache1.wait();tache2.wait();std::cout << "Fin des taches : global = " << global << " ("
<< 2*iterations << ")" << std::endl;return 0;
}
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 14 / 39
global = global + 1;std::cout << "I got the mutex" << std::endl;mutex.unlock(); Ne pas oublier
}else
std::cout << "I cannot get the mutex" << std::endl;}
}};
int main(void) {MyThread tache1, tache2;tache1.start();tache2.start();tache1.wait();tache2.wait();std::cout << "Fin des taches : global = " << global << " ("
<< 2*iterations << ")" << std::endl;return 0;
}
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 14 / 39
A éviter:sem_trywait(sem_t *sem)sem_getvalue(sem_t *sem,int *sval)
Fichier à inclure: #include <semaphore.h>
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 21 / 39
Sémaphores Introduction
Sémaphores: Création et destruction
Constructeur
QSemaphore::QSemaphore(int n = 0);
Crée un sémaphore et l’initialise à la valeur spécifiée;
Dans le cadre du cours, interdiction de l’initialiser à une valeur négative
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 22 / 39
Sémaphores Introduction
Sémaphores: Attente
void acquire(int n=1);
Décrémente (bloque) le sémaphore spécifié. Si la valeur du sémaphoreest > 0, sa valeur est décrémentée et la fonction retourne immédiatement;
Si sa valeur est égal à 0, alors l’appel bloque jusqu’à ce que sa valeurdevienne > 0;
Dans le cadre du cours, interdiction d’utiliser n > 1.
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 23 / 39
Sémaphores Introduction
Sémaphores: Attente
bool tryAcquire(int n=1);
Identique à acquire, sauf que si la décrémentation ne peut pas avoirlieu, la fonction renvoie false au lieu de bloquer
Renvoie true en cas de succès et false si la valeur du sémaphore estplus petite ou égale à 0.
Dans le cadre du cours, interdiction d’utiliser n > 1.
Nous n’utiliserons pas cette fonction dans ce cours.
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 24 / 39
Sémaphores Introduction
Sémaphores: Signalisation
void release(int n=1);
Incrémente (débloque) le sémaphore spécifié;
Si la valeur du sémaphore devient > 0, alors un autre thread bloqué dansun appel à acquire sera débloqué de la file d’attente et pourra effectuerl’opération de décrémentation (déblocage);
Dans le cadre du cours nous n’utiliserons pas de valeur de n > 1.
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 25 / 39
Sémaphores Introduction
Sémaphores: exemple
#define NUM_THREADS 4QSemaphore *sem;
class MyThread : public QThread{
int tid;public:
MyThread(int id) : tid(id) {};void run() {
sem->acquire();cout << "Tache " << tid << " est rentrée en SC" << endl;sleep((int)((float)3*rand()/(RAND_MAX+1.0)));cout << "Tache " << tid << " sort de la SC" << endl;sem->release();
}};
int main(void){
int i;QThread *threads[NUM_THREADS];sem = new QSemaphore(2);for (i = 0; i < NUM_THREADS; i++) {
threads[i] = new MyThread(i);threads[i]->start();
}for (i = 0; i < NUM_THREADS; i++)
threads[i]->wait();return EXIT_SUCCESS;
}
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 26 / 39
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 38 / 39
Exercices
Exercice
Nous désirons réaliser une application possédant 2 tâches. Le programmeprincipal est en charge de lancer les deux tâches.Etant donné que les tâches, une fois lancées, doivent attendre un signal duprogramme principal pour s’exécuter, comment résoudre le problème à l’aidede sémaphores?
Y. Thoma (HES-SO / HEIG-VD / REDS) Introduction à la programmation concurrente Février 2017 39 / 39