Atomics and mutex
The code is in
hands-on/memory/atomics_mutex.
Exercise 1: the counter of the slides
counter.cc is the program of the slides: two threads increment the same int one million
times each.
g++ -O0 -pthread counter.cc -o counter
./counter
- Run it a few times. Is the result 2,000,000? Why not?
- Compile with
-O2and run again. Does it work? Do you think your program is correct? - Fix it with
std::atomic, and check the result at-O0and-O2.
Exercise 2: producer and consumer
Modify atomics.cc. A producer thread fills a vector; a consumer thread reads the vector and
sums its elements, then checks the sum.
g++ -O2 -pthread atomics.cc -o atomics
./atomics
- Is the sum always correct? Try different optimisation levels.
- Fix it with an atomic flag: the producer sets it when it has finished, and the consumer waits
for it before reading. Which memory order do the store and the load need? Would a plain
boolwork?
Exercise 3: even and odd numbers with a mutex
Modify mutex.cc: count the even and the odd numbers of a vector in parallel, with
std::thread.
- Split the vector into one chunk per thread. Make sure the chunks cover the whole vector, also when its size is not a multiple of the number of threads.
- Use a
std::mutexso that the two shared counters are correct. Usestd::lock_guardinstead of callinglock()andunlock()by hand: why? - How often does each thread need to lock the mutex? Compare locking once per element with locking once per thread.
- Then try with
std::atomic<int>counters instead of the mutex.
g++ -std=c++20 -Wall -O2 -pthread mutex.cc -o mutex
./mutex