...

/

One Time Synchronization of Threads

One Time Synchronization of Threads

Explore one-time synchronization of threads with examples.

Sender-receiver workflows are quite common for threads. In such a workflow, the receiver is waiting for the sender’s notification before Future continues to work. There are various ways to implement these workflows. With C++11, you can use condition variables or promise/future pairs; with C++20, you can use std::atomic_flag. Each way has its pros and cons. Consequently, I want to compare them. I assume you don’t know the details of condition variables or promises and futures. Therefore, I provide a short refresher.

Condition variables

A condition variable can fulfill the role of a sender or a receiver. As a sender, it can notify one or more receivers.

Run the following program 4 times and notice the output.

Press + to interact
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <vector>
std::mutex mut;
std::condition_variable condVar;
std::vector<int>myVec{};
void prepareWork() {
{
std::lock_guard<std::mutex> lck(mut);
myVec.insert(myVec.end(), {0, 1, 0, 3});
}
std::cout << "Sender: Data prepared." << '\n';
condVar.notify_one();
}
void completeWork() {
std::cout << "Waiter: Waiting for data." << '\n';
std::unique_lock<std::mutex> lck(mut);
condVar.wait(lck, []{ return not myVec.empty(); });
myVec[2] = 2;
std::cout << "Waiter: Complete the work." << '\n';
for (auto i: myVec) std::cout << i << " ";
std::cout << '\n';
}
int main() {
std::cout << '\n';
std::thread t1(prepareWork);
std::thread t2(completeWork);
t1.join();
t2.join();
std::cout << '\n';
}

The program has two child threads: t1 ...