C++ - Threading Utilities (C++20)
Overview
Estimated time: 60–80 minutes
Modern synchronization and lifetime helpers: jthread with automatic join, cooperative cancellation, latches/barriers for phase control, and semaphores for permits.
Learning Objectives
- Use std::jthread for RAII-style threads and cooperative cancellation.
- Coordinate threads with std::latch/std::barrier.
- Throttle concurrency using std::counting_semaphore.
Prerequisites
jthread and stop_token
#include
#include
#include
#include
int main(){
std::jthread worker([](std::stop_token st){
using namespace std::chrono_literals;
while(!st.stop_requested()){
std::this_thread::sleep_for(10ms);
}
std::cout << "stopped\n";
});
worker.request_stop(); // cooperative cancel
}
latch and barrier
#include
#include
#include
#include
#include
int main(){
std::latch start(1);
std::barrier phase(4);
std::vector threads;
for (int i=0;i<3;++i){
threads.emplace_back([&]{
start.wait(); // all start together
phase.arrive_and_wait(); // phase 1 done
phase.arrive_and_wait(); // phase 2 done
});
}
start.count_down();
for (auto& t: threads) t.join();
std::cout << "ok\n";
}
counting_semaphore
#include
#include
#include
#include
int main(){
std::counting_semaphore sem(2); // 2 permits
auto task=[&]{ sem.acquire(); std::cout<<"run\n"; sem.release(); };
std::vector v(5);
for(auto& t: v) t = std::thread(task);
for(auto& t: v) t.join();
}
Common Pitfalls
- Not checking stop_token regularly; cancellation stays cooperative.
- Deadlocks with barriers if participant count mismatches arrivals.
Checks for Understanding
- How does jthread differ from thread?
- When to use a semaphore vs a mutex?
Show answers
- jthread joins automatically on destruction and carries a stop_token.
- Semaphore limits concurrency (permits), mutex protects critical sections.
Exercises
- Use jthread + stop_token to implement a cancellable periodic task.
- Limit concurrent downloads to N using counting_semaphore.