Nous supposons que nous avons deux fonctions, une première fonction calcule la valeur maximale d’un tableau numérique :
void array_find_max( std::vector<int>::const_iterator begin, std::vector<int>::const_iterator end, int* theMaxValue) { if (begin != end) { int result = *begin; begin++; for (; begin != end; begin++) if (*begin > result) result = *begin; *theMaxValue = result; } }
la seconde fonction modifie le tableau en multipliant chaque valeur numérique du tableau par 2 :
void array_multiply_by( std::vector<int>::iterator begin, std::vector<int>::iterator end, int theValue) { for (; begin != end; begin++) *begin *= theValue; }
Implanter chacune des fonctions.
Pour tester les fonctions, nous devons créer des tableaux de taille conséquente. Ces tableaux peuvent-être créés par soit de manière aléatoire soit de manière cycliques. Ci-dessous quelques exemples de fonctions générant des tableaux de taille n
et ayant comme valeur des nombres entre 0
et theMaxValue
.
Nous souhaitons exécuter en parallèle les deux fonctions.
void initialize_array(std::vector<int>& theArray, int theSize, int theMaxValue) { theArray.clear(); theArray.resise(theSize); int step = theMaxValue / 3; theArray[0] = 0; for (int i = 1; i < theSize; i++) theArray[i] = (theArray[i-1] + step) % (theMaxValue + 1); }
Ou
#include<random> void initialize_random_array(std::vector<int>& theArray, int theSize, int theMaxValue) { static std::mt19937 gen(1729); std::uniform_int_distribution<> distrib(0, theMaxValue); theArray.clear(); for (int i = 0; i < theSize; i++) theArray[i] = distrib(gen); }
Nous souhaitons exécuter les deux fonctions précédents en parallèle.
Expliquer pourquoi les résultats ne sont pas toujours cohérents ? ie. que la valeur maximale retournée est supérieure à la valeur maximale du tableau spécifiée au montant de sa création.
Il faut utiliser un verrou qui permet à une méthode de se garantir l’exclusivité de l’usage du tableau. Pour ce faire, nous pouvons utiliser un objet std::mutex qui encapsule un mécanisme d’exclusion mutuelle. L’objet std::unique_lock permet d’obtenir un accès exclusif sur un object std::mutex. Quand nous écrivons le code suivant :
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock std::mutex mtx; // mutex fournissant le mécanisme d’exclusion mutuelle. void my_function (int n, char c) { // section critique, tant que l'objet lck existe, personne ne pourra // accéder à mtx. std::unique_lock<std::mutex> lck(mtx); // Code s'exécutant. }
Modifier les fonctions
int array_find_max(std::vector<int>& theArray, int* theMaxValue)
et
void array_multiply_by(std::vector<int>& theArray, int theValue)
pour implanter le mécanisme d’exclusion mutuelle propose.
Exécuter le code et vérifier que les résultats sont dorénavant cohérents.