...

/

Acquire Release: The Typical Misunderstanding

Acquire Release: The Typical Misunderstanding

This lesson highlights a typical misunderstanding while using acquire-release in C++.

We'll cover the following...

What is my motivation for writing about the typical misunderstanding of the acquire-release semantic? Many of my readers and students have already fallen into this trap. Let’s look at the straightforward case. Here is a simple program as a starting point.

Press + to interact
// acquireReleaseWithWaiting.cpp
#include <atomic>
#include <iostream>
#include <thread>
#include <vector>
std::vector<int> mySharedWork;
std::atomic<bool> dataProduced(false);
void dataProducer(){
mySharedWork = {1, 0, 3};
dataProduced.store(true, std::memory_order_release);
}
void dataConsumer(){
while( !dataProduced.load(std::memory_order_acquire) );
mySharedWork[1] = 2;
}
int main(){
std::cout << std::endl;
std::thread t1(dataConsumer);
std::thread t2(dataProducer);
t1.join();
t2.join();
for (auto v: mySharedWork){
std::cout << v << " ";
}
std::cout << "\n\n";
}

The consumer thread t1 in line 17 waits until the consumer thread t2 in line 13 sets dataProduced to true. dataProduced is the guard and it guarantees that access to the non-atomic variable mySharedWork is synchronized. This means that the producer thread t2 initializes mySharedWork, then the consumer thread t1 finishes the work by setting mySharedWork[1] ...