How can thread interaction be synchronized?
sobes.tech AI
Answer from AI
There are several main mechanisms for synchronization of interaction between threads in C/C++:
-
Mutexes: Provide exclusive access to a shared resource. A thread that has acquired a mutex blocks other threads from acquiring it until it releases the mutex.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Acquire mutex // Work with shared resource my_mutex.unlock(); // Release mutex }Or using RAII:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Acquire mutex upon object creation // Work with shared resource // Mutex will be automatically released when the lock object goes out of scope } -
Semaphores: Generalization of mutexes. They maintain a counter that allows a specified number of threads to access a resource simultaneously.
#include <semaphore.h> // For POSIX semaphores #include <windows.h> // For Windows semaphores sem_t my_semaphore; // POSIX semaphore void my_thread_function() { sem_wait(&my_semaphore); // Decrease semaphore counter, block if zero // Work with resource sem_post(&my_semaphore); // Increase semaphore counter }(Note: Standard C++ does not include semaphores directly, but they are available through system libraries or third-party implementations.)
-
Condition Variables: Used for a thread to wait for a certain condition to occur, releasing the mutex during the wait. Another thread can notify the waiting thread when the condition is met.
#include <mutex> #include <condition_variable> std::mutex my_mutex; std::condition_variable my_cv; bool condition_met = false; void waiting_thread() { std::unique_lock<std::mutex> lock(my_mutex); my_cv.wait(lock, []{ return condition_met; }); // Wait for condition // Condition met, work with resource } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Optionally unlock before notifying my_cv.notify_one(); // Notify one waiting thread // or // my_cv.notify_all(); // Notify all waiting threads } -
Atomic Operations: Allow performing simple operations on variables (e.g., increment, decrement) as a single, indivisible action without explicit mutex locking.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Atomic increment // Or: // counter.fetch_add(1); } -
Read-Write Locks (Shared Mutexes): Allow multiple threads to read data simultaneously, but only one thread to write data.
#include <shared_mutex> // C++17 and above std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Acquire for reading // Read data my_shared_mutex.unlock_shared(); // Release for reading } void write_thread() { my_shared_mutex.lock(); // Acquire for writing (exclusive) // Write data my_shared_mutex.unlock(); // Release for writing } -
Barriers: Allow a group of threads to wait until all have reached a certain point in their execution before continuing.
#include <barrier> // C++20 std::barrier sync_point(4); // Barrier for 4 threads void my_thread_function() { // Work before barrier sync_point.arrive_and_wait(); // Wait until all threads reach the barrier // Work after barrier }
The choice of a specific mechanism depends on the nature of interaction and shared resources.