Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Вивчайте Mutexes and Locks | Synchronization and Communication
C++ Concurrency and Multithreading

bookMutexes and Locks

Mutual exclusion is a fundamental concept in concurrent programming that ensures only one thread accesses a shared resource at a time. In C++, the std::mutex class provides a way to enforce this rule. When multiple threads attempt to read or modify shared data simultaneously, their actions can overlap in unpredictable ways, leading to bugs known as race conditions. By using a mutex, you can create a region in your code where only one thread is allowed to execute at a time, protecting your shared resources from concurrent access issues.

main.cpp

main.cpp

copy
12345678910111213141516171819202122232425262728293031
#include <iostream> #include <thread> #include <mutex> #include <vector> std::mutex counter_mutex; int counter = 0; void increment_counter(int times) { for (int i = 0; i < times; ++i) { std::lock_guard<std::mutex> lock(counter_mutex); ++counter; } } int main() { const int num_threads = 4; const int increments_per_thread = 100000; std::vector<std::thread> threads; for (int i = 0; i < num_threads; ++i) threads.emplace_back(increment_counter, increments_per_thread); for (auto& t : threads) t.join(); std::cout << "Final counter value: " << counter << std::endl; }

In this example, you use a std::mutex named counter_mutex to guard access to the shared counter variable. Each thread attempts to increment the counter many times, but only one thread may enter the critical section—the code between acquiring and releasing the mutex—at a time. This prevents race conditions and ensures that the final value of counter is correct.

Note
Study More

Critical section refers to a part of a program where shared resources are accessed or modified. If multiple threads enter a critical section simultaneously without protection, race conditions can occur, leading to incorrect or unpredictable results. Mutexes are synchronization primitives that prevent race conditions by ensuring only one thread can enter the critical section at any moment.

When using mutexes, you need a convenient and reliable way to acquire and release them. C++ offers two main RAII-based locking mechanisms for this: std::lock_guard and std::unique_lock. Both are designed to lock a mutex when created and automatically release it when destroyed, but they differ in features and use cases.

std::lock_guard
expand arrow
  • Simple, lightweight wrapper for locking a mutex;
  • Locks the mutex upon construction and unlocks upon destruction;
  • Cannot be unlocked before the end of its scope;
  • Minimal overhead; best for straightforward, scope-based locking.
std::unique_lock
expand arrow
  • More flexible than lock_guard;
  • Can be locked and unlocked multiple times within its scope;
  • Supports deferred locking and timed locking;
  • Slightly more overhead; suitable for complex locking scenarios or when lock ownership needs to be transferred.

Choosing between std::lock_guard and std::unique_lock depends on your requirements. If you only need to lock a mutex for a simple scope, std::lock_guard is ideal. If you need to lock and unlock multiple times or require advanced features, std::unique_lock is the better choice.

question mark

Which locking mechanism would you choose if you need to temporarily release a mutex and later reacquire it within the same scope?

Select the correct answer

Все було зрозуміло?

Як ми можемо покращити це?

Дякуємо за ваш відгук!

Секція 2. Розділ 1

Запитати АІ

expand

Запитати АІ

ChatGPT

Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат

Suggested prompts:

Can you explain the difference between std::lock_guard and std::unique_lock in more detail?

What are some common mistakes to avoid when using mutexes in C++?

Can you provide an example of using std::unique_lock with advanced features?

bookMutexes and Locks

Свайпніть щоб показати меню

Mutual exclusion is a fundamental concept in concurrent programming that ensures only one thread accesses a shared resource at a time. In C++, the std::mutex class provides a way to enforce this rule. When multiple threads attempt to read or modify shared data simultaneously, their actions can overlap in unpredictable ways, leading to bugs known as race conditions. By using a mutex, you can create a region in your code where only one thread is allowed to execute at a time, protecting your shared resources from concurrent access issues.

main.cpp

main.cpp

copy
12345678910111213141516171819202122232425262728293031
#include <iostream> #include <thread> #include <mutex> #include <vector> std::mutex counter_mutex; int counter = 0; void increment_counter(int times) { for (int i = 0; i < times; ++i) { std::lock_guard<std::mutex> lock(counter_mutex); ++counter; } } int main() { const int num_threads = 4; const int increments_per_thread = 100000; std::vector<std::thread> threads; for (int i = 0; i < num_threads; ++i) threads.emplace_back(increment_counter, increments_per_thread); for (auto& t : threads) t.join(); std::cout << "Final counter value: " << counter << std::endl; }

In this example, you use a std::mutex named counter_mutex to guard access to the shared counter variable. Each thread attempts to increment the counter many times, but only one thread may enter the critical section—the code between acquiring and releasing the mutex—at a time. This prevents race conditions and ensures that the final value of counter is correct.

Note
Study More

Critical section refers to a part of a program where shared resources are accessed or modified. If multiple threads enter a critical section simultaneously without protection, race conditions can occur, leading to incorrect or unpredictable results. Mutexes are synchronization primitives that prevent race conditions by ensuring only one thread can enter the critical section at any moment.

When using mutexes, you need a convenient and reliable way to acquire and release them. C++ offers two main RAII-based locking mechanisms for this: std::lock_guard and std::unique_lock. Both are designed to lock a mutex when created and automatically release it when destroyed, but they differ in features and use cases.

std::lock_guard
expand arrow
  • Simple, lightweight wrapper for locking a mutex;
  • Locks the mutex upon construction and unlocks upon destruction;
  • Cannot be unlocked before the end of its scope;
  • Minimal overhead; best for straightforward, scope-based locking.
std::unique_lock
expand arrow
  • More flexible than lock_guard;
  • Can be locked and unlocked multiple times within its scope;
  • Supports deferred locking and timed locking;
  • Slightly more overhead; suitable for complex locking scenarios or when lock ownership needs to be transferred.

Choosing between std::lock_guard and std::unique_lock depends on your requirements. If you only need to lock a mutex for a simple scope, std::lock_guard is ideal. If you need to lock and unlock multiple times or require advanced features, std::unique_lock is the better choice.

question mark

Which locking mechanism would you choose if you need to temporarily release a mutex and later reacquire it within the same scope?

Select the correct answer

Все було зрозуміло?

Як ми можемо покращити це?

Дякуємо за ваш відгук!

Секція 2. Розділ 1
some-alt