Logs
Consultez les logs.
OK
Liste des données
Consultez la liste des données.
OK
Loading...
Formulaire
Saisissez vos données.
Enregistrer
Annuler

Concepts du C++

Vues
140

Introduction


C++ est un langage de programmation orientée objet. Il offre la possibilité d'avoir le contrôle total sur la gestion de la mémoire.


### Travailler avec le Multithreading


C++ est un langage de programmation orientée objet prenant en charge la programmation Multithreading. Le Multithreading permet d'exécuter plusieurs processus en parallèle de manière asynchrone dans des threads séparés.


Multithreading


C++ est un langage de programmation orientée objet prenant en charge la programmation Multithreading. Le Multithreading permet d'exécuter plusieurs processus en parallèle de manière asynchrone dans des threads séparés. 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 remarquerons que le module d'affichage (std::cout) n'est pas atomique sur toutes les plateformes (il ne s'exécute pas en une seule instruction ou il peut être interrompu par un autre thread que celui qui l'utilise).


Gestion du programme principal


// main.cpp (Editer le programme principal)
...
#include <iostream>
#include <thread>
#include <chrono>

using namespace std::chrono_literals;

static void onThread(const std::string &_name);

int main(int _argc, char **_argv)
{
    std::thread oThreadA(onThread, "[ThreadA]");
    std::thread oThreadB(onThread, "[ThreadB]");
    oThreadA.join();
    oThreadB.join();
    return 0;
}

static void onThread(const std::string &_name)
{
    std::cout << _name << " : " << "Demarrage du traitement." << std::endl;
    std::this_thread::sleep_for(1s);
    std::cout << _name << " : " << "Fin du traitement." << std::endl;
}
...

Gestion du fichier CMake


// 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 11)

add_executable(${PROJECT_NAME}
    main.cpp
)
...

Exécution du projet


// Terminal (Exécuter le projet)
...
rdvcpp.exe
...

// Application (Opérations sur l'exécution des threads)
// Application (Opérations sur l'absence d'atomicité lors de l'affichage)
// Application (Observations : B imprime alors A est en cours)
// Application (Opérations sur le comportement imprévisible des threads)
// Application (Observations : B démarre alors que A est en cours)

image.png


Multithreading | Mutex | std::unique_lock


C++ est un langage de programmation orientée objet prenant en charge l'exclusion mutuelle (Mutex) 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. L'exclusion mutuelle (Mutex) permet de protéger une ressource partagée afin de synchroniser les threads lors d'un accès concurrent. Une exclusion mutuelle (Mutex) ne peut être verrouillée et déverrouillée que par le thread qui l'utilise. 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 (mutex) pour mettre en place l'exclusion mutuelle des threads. Nous utiliserons le module (std::unique_lock) afin de verrouiller et de déverrouiller manuellement l'accès à la ressource partagée.



Gestion du programme principal


// main.cpp (Editer le programme principal)
...
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>

static std::mutex gMutex;

using namespace std::chrono_literals;

static void onThread(const std::string &_name);

int main(int _argc, char **_argv)
{
    std::thread oThreadA(onThread, "[ThreadA]");
    std::thread oThreadB(onThread, "[ThreadB]");
    oThreadA.join();
    oThreadB.join();
    return 0;
}

static void onThread(const std::string &_name)
{
    std::unique_lock<std::mutex> oLock(gMutex);
    std::cout << _name << " : " << "Demarrage du traitement." << std::endl;
    std::this_thread::sleep_for(1s);
    std::cout << _name << " : " << "Fin du traitement." << std::endl;
    oLock.unlock();
}
...

Gestion du fichier CMake


// 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 11)

add_executable(${PROJECT_NAME}
    main.cpp
)
...

Exécution du projet


// 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 : A démarre et termine avant que B ne commence)
// Application (Observations : A imprime et termine avant que B ne commence)

image.png


Multithreading | Mutex | std::lock_guard


C++ est un langage de programmation orientée objet prenant en charge l'exclusion mutuelle (Mutex) 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. L'exclusion mutuelle (Mutex) permet de protéger une ressource partagée afin de synchroniser les threads lors d'un accès concurrent. Une exclusion mutuelle (Mutex) ne peut être verrouillée et déverrouillée que par le thread qui l'utilise. 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 (mutex) pour mettre en place l'exclusion mutuelle des threads. Nous utiliserons le module (std::lock_guard) afin de verrouiller et de déverrouiller automatiquement l'accès à la ressource partagée.


Gestion du programme principal


// main.cpp (Editer le programme principal)
...
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>

static std::mutex gMutex;

using namespace std::chrono_literals;

static void onThread(const std::string &_name);

int main(int _argc, char **_argv)
{
    std::thread oThreadA(onThread, "[ThreadA]");
    std::thread oThreadB(onThread, "[ThreadB]");
    oThreadA.join();
    oThreadB.join();
    return 0;
}

static void onThread(const std::string &_name)
{
    std::lock_guard<std::mutex> oLock(gMutex);
    std::cout << _name << " : " << "Demarrage du traitement." << std::endl;
    std::this_thread::sleep_for(1s);
    std::cout << _name << " : " << "Fin du traitement." << std::endl;
} 
...

Gestion du fichier CMake


// 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 11)

add_executable(${PROJECT_NAME}
    main.cpp
)
...

Exécution du projet


// 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 : A démarre et termine avant que B ne commence)
// Application (Observations : A imprime et termine avant que B ne commence)

image.png


Multithreading | Sémaphore | std::binary_semaphore


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::binary_semaphore) pour mettre en place l'exclusion mutuelle des threads en concurrence. Le module (std::binary_semaphore) est l'équivalent du module (std::counting_semaphore) avec un seul thread autorisé à accéder la ressource partagée. Nous utiliserons la méthode (acquire) afin d'acquérir et verrouiller l'accès à la ressource partagée. Nous utiliserons la méthode (release) afin de libérer et déverrouiller l'accès à la ressource partagée. 


Gestion du programme principal


// main.cpp (Editer le programme principal)
...
#include <iostream>
#include <thread>
#include <chrono>
#include <semaphore>

static const int DEF_SEMAPHORE_INIT_LOCKED = 0;
static const int DEF_SEMAPHORE_INIT_UNLOCKED = 1;

static std::binary_semaphore gSemaphore(DEF_SEMAPHORE_INIT_UNLOCKED);

using namespace std::chrono_literals;

static void onThread(const std::string &_name);

int main(int _argc, char **_argv)
{
    std::thread oThreadA(onThread, "[ThreadA]");
    std::thread oThreadB(onThread, "[ThreadB]");
    oThreadA.join();
    oThreadB.join();
    return 0;
}

static void onThread(const std::string &_name)
{
    gSemaphore.acquire();
    std::cout << _name << " : " << "Demarrage du traitement." << std::endl;
    std::this_thread::sleep_for(1s);
    std::cout << _name << " : " << "Fin du traitement." << std::endl;
    gSemaphore.release();
}
...

Gestion du fichier CMake


// 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
)
...

Exécution du projet


// 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 : B démarre et termine avant que A ne commence)
// Application (Observations : B imprime et termine avant que A ne commence)

image.png


Multithreading | Sémaphore | std::counting_semaphore


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 remarquerons que le module d'affichage (std::cout) n'est pas atomique sur toutes les plateformes (il ne s'exécute pas en seule instruction ou il peut être interrompu par un autre thread que celui qui l'utilise). 


Gestion du programme principal


// main.cpp (Editer le programme principal)
...
#include <iostream>
#include <vector>
#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::cout << _name << " : " << "En attente de traitement." << std::endl;
    gSemaphore.acquire();
    std::cout << _name << " : " << "Demarrage du traitement." << std::endl;
    std::this_thread::sleep_for(1s);
    std::cout << _name << " : " << "Fin du traitement." << std::endl;
    gSemaphore.release();
}
...

Gestion du fichier CMake


// 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
)
...

Exécution du projet


// 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 (Opérations sur l'absence d'atomicité lors de l'affichage)
// Application (Observations : C imprime alors A est en cours)

image.png
image.png


Multithreading | Sémaphore | std::counting_semaphore | sstream


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). 


Gestion du programme principal


// 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();
}
...

Gestion du fichier CMake


// 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
)
...

Exécution du projet


// 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)

image.png
image.png