C++ high performance: std multithreading thread, mutex, condition_variable future

mutex

std::mutex

  • std::mutex mtx;,mtx.lock();,mtx.unlock();
// https://cplusplus.com/reference/mutex/mutex/
// mutex example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex

std::mutex mtx; // mutex for critical section

void print_block (int n, char c) {<!-- -->
  // critical section (exclusive access to std::cout signaled by locking mtx):
  mtx. lock();
  for (int i=0; i<n; + + i) {<!-- --> std::cout << c; }
  std::cout << '\\
';
  mtx. unlock();
}

int main()
{<!-- -->
  std::thread th1 (print_block,50,'*');
  std::thread th2(print_block,50,'$');

  th1. join();
  th2. join();

  return 0;
}

std::unique_lock, with the function of automatic locking and unlocking

  • std::mutex mtx;
  • std::unique_lock lck(mtx);

atomic

  • std::atomic value;
  • int64_t x = 10;value.store(x,std::memory_order_relaxed)
  • int64_t x = value.load(std::memory_order_relaxed);
// atomic::load/store example
#include <iostream> // std::cout
#include <atomic> // std::atomic, std::memory_order_relaxed
#include <thread> // std::thread

std::atomic<int> foo (0);# https://zh.cppreference.com/w/cpp/atomic/atomic !!!!

void set_foo(int x) {<!-- -->
  foo.store(x,std::memory_order_relaxed); // set value atomically
}

void print_foo() {<!-- -->
  int x;
  do {<!-- -->
    x = foo.load(std::memory_order_relaxed); // get value atomically
  } while (x==0);
  std::cout << "foo: " << x << '\\
';
}

int main()
{<!-- -->
  std::thread first (print_foo);
  std::thread second(set_foo,10);
  first. join();
  second. join();
  return 0;
}
 Edit & run on cpp.sh

condition_variable

  • std::condition_variable cv;
  • cv.notify_all();//cv.notify_one(); //Wake up
  • cv.wait(lck);//Waiting to be woken up
// https://cplusplus.com/reference/condition_variable/condition_variable/
// condition_variable example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id (int id) {<!-- -->
  std::unique_lock<std::mutex> lck(mtx);//unique_lock has the function of automatic locking and unlocking
  while (!ready) // if(!ready) there is a spurious wakeup
    cv.wait(lck);//waiting to be woken up
  //...
  std::cout << "thread " << id << '\\
';
}

void go() {<!-- -->
  std::unique_lock<std::mutex> lck(mtx);
  ready = true;
  cv.notify_all();//cv.notify_one(); //Wake up
}

int main()
{<!-- -->
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; + + i)
    threads[i] = std::thread(print_id,i);

  std::cout << "10 threads ready to race...\\
";
  go(); // go!

  for (auto & amp; th : threads) th. join();

  return 0;
}

promise (set and get)

  • std::promise accumulate_promise;
  • std::future accumulate_future = accumulate_promise.get_future();// return the result associated with the promise
  • accumulate_promise.set_value(sum);
  • accumulate_future.get()

simple use

// changed on https://en.cppreference.com/w/cpp/thread/promise
#include <vector>
#include <thread>
#include <future> // future object allows you to retrieve data, and promise allows you to provide data. The declaration of promise is located in the header file <future>
#include <numeric>
#include <iostream>
#include <chrono>

void accumulate(std::vector<int>::iterator first,
                std::vector<int>::iterator last,
                std::promise<int> accumulate_promise)
{
    int sum = std::accumulate(first, last, 0);
    accumulate_promise.set_value(sum); // Notify future
}



int main()
{
    // Demonstrate using promise<int> to transmit a result between threads.
    std::promise<int> accumulate_promise;
    std::future<int> accumulate_future = accumulate_promise.get_future();// return the future associated with the promised result, https://www.apiref.com/cpp-zh/cpp/thread/promise.html

    std::vector<int> numbers = { 1, 2, 3, 4, 5, 6 };



    std::thread work_thread(accumulate, numbers.begin(), numbers.end(),
                            std::move(accumulate_promise));
    std::cout << "result=" << accumulate_future.get() << '\\
';// wait std::promise<int> accumulate_promise.set_value(sum);

    work_thread. join(); // wait for thread completion

}

more

#include <vector>
#include <thread>
#include <future>
#include <numeric>
#include <iostream>
#include <chrono>

void accumulate(std::vector<int>::iterator first,
                std::future<int> & last,
                std::promise<int> accumulate_promise)
{<!-- -->
    std::vector<int>::iterator begin = first;
    int value = last. get();
    while (*begin != value){<!-- -->
        begin++;
    }

    int sum = std::accumulate(first, begin, 0);
    accumulate_promise.set_value(sum); // Notify future
}


int main()
{<!-- -->
    // Demonstrate using promise<int> to transmit a result between threads.
    std::vector<int> numbers = {<!-- --> 1, 2, 3, 4, 5, 6 };
    std::promise<int> accumulate_promise;
    std::future<int> accumulate_future = accumulate_promise. get_future();

    std::promise<int> last; last. set_value(4);
    std::future<int> last_f = last. get_future();

    std::thread work_thread(accumulate, numbers.begin(), std::ref(last_f),
                            std::move(accumulate_promise));


    std::cout << "result=" << accumulate_future.get() << '\\
';
    work_thread. join();

}

std::shared_future sharedfutureObjName; get multiple times

semaphore c++ 20

CG

  • https://www.bilibili.com/video/BV1XY41137Mh/?
  • https://cplusplus.com/reference/thread/thread/

  • std::ref is just trying to simulate reference passing, and it cannot really become a method that refers to thread. When passing references, we want to use parameter references instead of shallow copies, so ref must be used for reference passing
#include <vector>
#include <thread>
#include <future> // future object allows you to retrieve data, and promise allows you to provide data. The declaration of promise is located in the header file <future>
#include <numeric>
#include <iostream>
#include <chrono>

void accumulate(std::vector<int>::iterator first,
                std::vector<int>::iterator last,
                std::promise<int> & accumulate_promise)
{
    int sum = std::accumulate(first, last, 0);
    accumulate_promise.set_value(sum); // Notify future
}



int main()
{
    // Demonstrate using promise<int> to transmit a result between threads.
    std::promise<int> accumulate_promise;
    std::future<int> accumulate_future = accumulate_promise.get_future();// return the future associated with the promised result, https://www.apiref.com/cpp-zh/cpp/thread/promise.html

    std::vector<int> numbers = { 1, 2, 3, 4, 5, 6 };



    std::thread work_thread(accumulate, numbers.begin(), numbers.end(),
                            std::ref(accumulate_promise));
    std::cout << "result=" << accumulate_future.get() << '\\
';// wait std::promise<int> accumulate_promise.set_value(sum);

    work_thread. join(); // wait for thread completion

}