c++ synchronization primitives example programs

Sure! Here are some examples of synchronization primitives in C++ along with explanations for each step:

Example 1: Mutex

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void printMessage(const std::string& message) {
    std::lock_guard<std::mutex> lock(mtx);
    std::cout << message << std::endl;
}

int main() {
    std::thread t1(printMessage, "Hello");
    std::thread t2(printMessage, "World");

    t1.join();
    t2.join();

    return 0;
}

Explanation: 1. We include the necessary headers for using mutex, threads, and IO operations. 2. We declare a global mutex variable mtx. 3. We define a function printMessage that takes a string message as an argument and prints it. 4. Inside the printMessage function, we create a lock_guard object lock which locks the mutex mtx as soon as it is constructed. 5. The message is then printed to the console. 6. In the main function, we create two threads t1 and t2, which call the printMessage function with different messages. 7. We wait for both threads to finish their execution by calling join on each thread. 8. Finally, the program returns 0.

Example 2: Semaphore

#include <iostream>
#include <thread>
#include <semaphore.h>

sem_t sem;

void printMessage(const std::string& message) {
    sem_wait(&sem);
    std::cout << message << std::endl;
    sem_post(&sem);
}

int main() {
    sem_init(&sem, 0, 1);

    std::thread t1(printMessage, "Hello");
    std::thread t2(printMessage, "World");

    t1.join();
    t2.join();

    sem_destroy(&sem);

    return 0;
}

Explanation: 1. We include the necessary headers for using semaphores, threads, and IO operations. 2. We declare a semaphore variable sem. 3. We define a function printMessage that takes a string message as an argument and prints it. 4. Inside the printMessage function, we call sem_wait to decrement the semaphore value by 1, effectively acquiring the semaphore. 5. The message is then printed to the console. 6. After printing the message, we call sem_post to increment the semaphore value by 1, releasing the semaphore. 7. In the main function, we initialize the semaphore sem with an initial value of 1. 8. We create two threads t1 and t2, which call the printMessage function with different messages. 9. We wait for both threads to finish their execution by calling join on each thread. 10. Finally, we destroy the semaphore using sem_destroy. 11. The program returns 0.

These examples demonstrate the use of two common synchronization primitives in C++, mutex and semaphore, to ensure thread-safe access to shared resources. The mutex guarantees that only one thread can execute the critical section of code at a time, while the semaphore allows a specified number of threads to access a shared resource concurrently.