Concurrency and Source Panels
Mutex Counter
Protect a shared counter with a mutex when multiple threads update it.
Mutex Counter
mutex_counter.cpp
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
void addSteps(int increments, int* counter, std::mutex* counterMutex) {
for (int step = 0; step < increments; ++step) {
std::lock_guard<std::mutex> guard(*counterMutex);
*counter += 1;
}
}
int main() {
int increments = ;
int counter = 0;
std::mutex counterMutex;
std::vector<std::thread> workers;
for (int worker = 0; worker < 2; ++worker) {
workers.emplace_back(addSteps, increments, &counter, &counterMutex);
}
for (int i = 0; i < 2; ++i) {
workers[i].join();
}
std::cout << "increments=" << increments << std::endl;
std::cout << "counter=" << counter << std::endl;
return 0;
}
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
void addSteps(int increments, int* counter, std::mutex* counterMutex) {
for (int step = 0; step < increments; ++step) {
std::lock_guard<std::mutex> guard(*counterMutex);
*counter += 1;
}
}
int main() {
int increments = ;
int counter = 0;
std::mutex counterMutex;
std::vector<std::thread> workers;
for (int worker = 0; worker < 2; ++worker) {
workers.emplace_back(addSteps, increments, &counter, &counterMutex);
}
for (int i = 0; i < 2; ++i) {
workers[i].join();
}
std::cout << "increments=" << increments << std::endl;
std::cout << "counter=" << counter << std::endl;
return 0;
}
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
void addSteps(int increments, int* counter, std::mutex* counterMutex) {
for (int step = 0; step < increments; ++step) {
std::lock_guard<std::mutex> guard(*counterMutex);
*counter += 1;
}
}
int main() {
int increments = ;
int counter = 0;
std::mutex counterMutex;
std::vector<std::thread> workers;
for (int worker = 0; worker < 2; ++worker) {
workers.emplace_back(addSteps, increments, &counter, &counterMutex);
}
for (int i = 0; i < 2; ++i) {
workers[i].join();
}
std::cout << "increments=" << increments << std::endl;
std::cout << "counter=" << counter << std::endl;
return 0;
}
lock
`std::lock_guard` holds the mutex for the rest of the current scope.
total
The final count is deterministic because every increment happens while the mutex is held.