本文转载自微信公众号《程序喵大师》,作者程序喵大师。转载本文请联系程序大师喵公众号。之前,我整理了一篇C++20新特性的文章,全网发布!!C++20的新特性都在这张图里,里面提到了latch、barrier和semaphore,但是没有详细介绍这三者。这里详细介绍两者的作用和区别。大多数人可能都知道latch,这就是我们经常使用的CountDownLatch。用于先做一个线程阻塞,等待其他线程完成工作再继续。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程数。每当一个线程完成它的任务时,计数器的值就会减1。当计数器的值达到0时,就意味着所有线程都完成了任务,此时等待的线程可以中断阻塞继续任务。我之前实现了一个CountDownLatch,源代码是这样的:;--count_;if(count_==0){cv_.notify_all();}}voidCountDownLatch::Await(int32_ttime_ms){std::unique_locklock(mutex_);while(count_>0){if(time_ms>0){cv_.wait_for(lock,std::chrono::milliseconds(time_ms));}else{cv_.wait(lock);}}}int32_tCountDownLatch::GetCount()const{std::unique_locklock(mutex_);returncount_;}barrier许多线程在阻塞点被阻塞。当到达阻塞点的线程数达到一定数量时,会执行完成回调,然后解除所有相关线程的阻塞,然后重置线程计数器。继续开始下一阶段的封锁。假设有很多线程并发执行,循环执行一些计算。进一步假设一旦这些计算完成,在线程开始其循环的新迭代之前需要对结果进行一些处理。看下面示例代码(摘自cppreference):#include#include#include#include#includeintmain(){constautoworkers={"anil","busara","carl"};autoon_completion=[]()noexcept{//lockingnotneededherestaticautophase="...done\n""Cleaningup...\n";std::cout<threads;for(autoconst&worker:workers){threads.emplace_back(work,worker);}for(auto&thread:threads){thread.join();}}可能的输出如下:Starting...anilworkedcarlworkedbusaraworked...doneCleaningup...busaracleanedcarlcleanedanilcleaned...donesemaphore信号量,这个估计大家不陌生,本质上也是一个计数器,主要有两个方法:为零,直到计数器递增release()再次:递增计数器(可以传递具体数字),并在acquire调用中解除线程阻塞。示例代码如下:#include#include#include#includestd::binary_semaphoresmphSignalMainToThread(0),smphSignalThreadToMain(0);voidThreadProc(){smphSignalMainToThread.acquire();std::cout<<"[thread]Gotthesignal\n";//使用命名空间响应消息std::literals;std::this_thread::sleep_for(3s);std::cout<<"[thread]Sendthesignal\n";//messagesmphSignalThreadToMain.release();}intmain(){std::threadthrWorker(ThreadProc);std::cout<<"[main]Sendthesignal\n";//messagesmphSignalMainToThread.release();smphSignalThreadToMain.acquire();std::cout<<"[main]Gotthesignal\n";//responsemessagethrWorker.join();}输出结果如下:[main]Sendthesignal[thread]Gotthesignal[thread]Sendthesignal[main]Gotthesignal信号量也可以作为一个条件变量,这个我估计大家应该都知道怎么做吧。今天就这样吧。