C++ est un langage de programmation orientée objet prenant en charge les
Sémaphores dans un contexte
Multithreading. Le Multithreading permet d'exécuter plusieurs processus en parallèle de manière asynchrone dans des threads séparés. Le Sémaphore permet de protéger une ressource partagée afin de synchroniser les threads lors d'un accès concurrent en y autorisant plusieurs threads. Un Sémaphore peut être verrouillé et déverrouillé par un autre thread que celui qui l'utilise. Un Sémaphore n'assure pas toujours l'exclusion mutuelle, à ne pas l'utiliser ou faire attention dans le cas de la modification d'une ressource partagée. Dans ce tutoriel, nous utiliserons le module (
thread) pour exécuter plusieurs processus en parallèle. Nous utiliserons la méthode (
join) pour attendre l'exécution de tous les threads avant de terminer le programme. Nous utiliserons le module (
std::counting_semaphore) pour synchroniser les threads en concurrence sans pour autant assurer leur exclusion mutuelle. Le module (std::counting_semaphore) est utilisé pour autoriser plusieurs threads à accéder à une ressource partagée. L'exclusion mutuelle est assurée uniquement lorsque le nombre maximale de threads autorisés est atteint. Nous utiliserons la méthode (
acquire) afin d'acquérir l'accès à la ressource partagée sans pour autant la verrouiller. Nous utiliserons la méthode (
release) afin de libérer l'accès à la ressource partagée sans pour autant la déverrouiller (si elle n'a pas été verrouillée précédemment). Nous utiliserons le module (
sstream) pour rendre le module d'affichage (
std::cout) atomique sur toutes les plateformes (pour qu'il s'exécute en une seule instruction ou pour qu'il ne soit pas interrompu par un autre thread que celui qui l'utilise).
// main.cpp (Editer le programme principal)...
#include <iostream>
#include <vector>
#include <sstream>
#include <thread>
#include <chrono>
#include <semaphore>
static const int DEF_SEMAPHORE_THREAD_MAX = 4;
static const int DEF_APP_THREAD_TOTAL = 10;
static std::counting_semaphore<DEF_SEMAPHORE_THREAD_MAX> gSemaphore(DEF_SEMAPHORE_THREAD_MAX);
using namespace std::chrono_literals;
static void onThread(const std::string &_name);
int main(int _argc, char **_argv)
{
std::vector<std::thread> oThreads;
for (int i = 0; i < DEF_APP_THREAD_TOTAL; i++)
{
oThreads.emplace_back(onThread, "[Thread" + std::string(1, 'A' + i) + "]");
}
for (auto &oThread : oThreads)
{
oThread.join();
}
return 0;
}
static void onThread(const std::string &_name)
{
std::stringstream oWaitMsg;
oWaitMsg << _name << " : " << "En attente de traitement." << std::endl;
std::cout << oWaitMsg.str();
gSemaphore.acquire();
std::stringstream oStartMsg;
std::stringstream oEndMsg;
oStartMsg << _name << " : " << "Demarrage du traitement." << std::endl;
oEndMsg << _name << " : " << "Fin du traitement." << std::endl;
std::cout << oStartMsg.str();
std::this_thread::sleep_for(1s);
std::cout << oEndMsg.str();
gSemaphore.release();
}
...
// CMakeLists.txt (Editer le fichier CMake)...
cmake_minimum_required(VERSION 3.10.0)
project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
add_executable(${PROJECT_NAME}
main.cpp
)
...
// Terminal (Exécuter le projet)...
rdvcpp.exe
...
// Application (Opérations sur l'exécution des threads)
// Application (Opérations sur la synchronisation des threads)
// Application (Observations : au départ on a 4 places disponibles)
// Application (Observations : ADEC démarrent, 0 places disponibles)
// Application (Observations : IJ attendent, 0 places disponibles)
// Application (Observations : EC terminent, 2 places disponibles)
// Application (Observations : FG démarrent, 0 places disponibles)
// Application (Observations : DA terminent, 2 places disponibles)
// Application (Observations : BH démarrent, 0 places disponibles)
// Application (Observations : HB terminent, 2 places disponibles)
// Application (Observations : FG terminent, 4 places disponibles)
// Application (Observations : IJ démarrent, 2 places disponibles)
// Application (Observations : JI terminent, 4 places disponibles)
// Application (Observations : A imprime et termine avant que D ne commence)