The following code example is taken from the book
C++20 - The Complete Guide by Nicolai M. Josuttis, Leanpub, 2021
The code is licensed under a Creative Commons Attribution 4.0 International License. Creative Commons License

// raw code

#include <iostream>
#include <array>
#include <algorithm>   // for std::fill_n()
#include <vector>
#include <format>
#include <random>
#include <thread>
#include <atomic>      // for std::atomic_ref<>
using namespace std::literals;  // for duration literals

int main()
  // create and initialize an array of integers with the value 100:
  std::array<int, 1000> values;
  std::fill_n(values.begin(), values.size(), 100);
  // initialize a common stop token for all threads:
  std::stop_source allStopSource;
  std::stop_token allStopToken{allStopSource.get_token()};

  // start multiple threads concurrently decrementing the value:
  std::vector<std::jthread> threads;
  for (int i = 0; i < 9; ++i) {
      [&values] (std::stop_token st) {
         // initialize random engine to generate an index:
         std::mt19937 eng{std::random_device{}()};
         std::uniform_int_distribution distr{0, int(values.size()-1)};

         while (!st.stop_requested()) {
           // compute the next index:
           int idx = distr(eng);

           // enable atomic access to the value with the index:
           std::atomic_ref val{values[idx]};

           // and use it:
           if (val <= 0) {
             std::cout << std::format("index {} is zero\n", idx);
      allStopToken  // pass the common stop token

  // after a while/event request to stop all threads:
  std::cout << "\nSTOP\n";