#include <thread>
#include <iostream>
void increment(int & counter)
{
for(size_t i = 0; i < 10000; i++)
{
counter++;
}
}
void decrement(int & counter)
{
for(size_t i = 0; i < 10000; i++)
{
counter--;
}
}
int main()
{
int counter;
std::thread t1(&increment, std::ref(counter));
std::thread t2(&decrement, std::ref(counter));
t1.join();
t2.join();
std::cout << counter << std::endl;
return 0;
}
C'est prévisible, le programme va afficher des nombres totalement farfelus en sortie, car counter n'est pas protégé.
Maintenant, protégeons counter:
#include <cstdatomic>
#include <thread>
#include <iostream>
void increment(std::atomic<int> & counter)
{
for(size_t i = 0; i < 10000; i++)
{
counter++;
}
}
void decrement(std::atomic<int> & counter)
{
for(size_t i = 0; i < 10000; i++)
{
counter--;
}
}
int main()
{
std::atomic<int> counter;
std::thread t1(&increment, std::ref(counter));
std::thread t2(&decrement, std::ref(counter));
t1.join();
t2.join();
std::cout << counter << std::endl;
return 0;
}
Magie de la technologie moderne, le programme affiche systématiquement un beau 0 tout rond. Un appel de la méthode is_lock_free() sur counter (atomic_is_lock_free() sur gcc 4.5, plus avancé au niveau des standards) vous dira si votre architecture supporte les instructions atomiques.
Voilà, c'est à peu près tout! A noter cependant que l'en-tête atomic a fait son arrivée dans gcc 4.5. Avec cette version, le programme d'exemple (de mémoire), serait (et avec les lambdas, s'il vous plait!):
#include <atomic>
#include <thread>
#include <iostream>
int main()
{
std::atomic<int> counter;
std::thread t1([&counter]()
{for(size_t i = 0; i < 10000; i++) counter++;});
std::thread t2([&counter]()
{for(size_t i = 0; i < 10000; i++) counter--;});
t1.join();
t2.join();
std::cout << counter << std::endl;
return 0;
}
Très belle présentation du mot clé. Très clair. Merci beaucoup.
RépondreSupprimerCe commentaire a été supprimé par l'auteur.
RépondreSupprimerSalut !
RépondreSupprimerJ'ai du chercher un peu avant de savoir comment on compile ton exemple. J'ai réussi comme ca :
g++ stdatomic.cpp -std=c++0x -pthread
A bientôt,
Ingo
Salut Ingo!
RépondreSupprimerEn effet, j'avais oublié de mettre la ligne de compile... Bien vu, et merci!
Ça ne sera pas forcément 0, mais la valeur à laquelle la variable a été affectée lors de son initialisation lors de l'exécution (un test sur mon système, gcc 4.6.x me l'a prouvé). Car autant que je sache, même le nouveau standard ne définit pas de valeur d'initialisation pour les types définis par défaut.
RépondreSupprimerBien vu, j'ai en effet oublié d'initialiser mon compteur.
RépondreSupprimer