C++入门到精通-C++20新特性的小细节
小职 2021-10-18 来源 :程序喵大人 阅读 612 评论 0

摘要:本文主要介绍了C++入门到精通-C++20新特性的小细节,通过具体的内容展现,希望对大家C++20有更深入的认识。

本文主要介绍了C++入门到精通-C++20新特性的小细节,通过具体的内容展现,希望对大家C++20有更深入的认识。

C++入门到精通-C++20新特性的小细节


 

 

C++20新特性中latch、barrier和semaphore,但是没有详细介绍过三者的作用和区别,这里详细介绍下。

 

latch

这个可能大多数人都有所了解,这就是我们经常会用到的CountDownLatch。用于使一个线程先阻塞,等待其他线程完成各自的工作后再继续执行。

 

CountDownLatch是通过计数器实现,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后等待的线程就可以打断阻塞去继续执行任务。

 

自己之前实现过一个CountDownLatch,源码大概这样:

 

CountDownLatch::CountDownLatch(int32_t count) : count_(count) {}

 

void CountDownLatch::CountDown() {

    std::unique_lock<std::mutex> lock(mutex_);

    --count_;

    if (count_ == 0) {

        cv_.notify_all();

    }

}

 

void CountDownLatch::Await(int32_t time_ms) {

    std::unique_lock<std::mutex> lock(mutex_);

    while (count_ > 0) {

        if (time_ms > 0) {

            cv_.wait_for(lock, std::chrono::milliseconds(time_ms));

        } else {

            cv_.wait(lock);

        }

    }

}

 

int32_t CountDownLatch::GetCount() const {

    std::unique_lock<std::mutex> lock(mutex_);

    return count_;

}

barrier

许多线程在阻塞点阻塞,当到达阻塞点的线程达到一定数量时,会执行完成的回调,然后解除所有相关线程的阻塞,然后重置线程计数器,继续开始下一阶段的阻塞。

 

假设有很多线程并发执行,并在一个循环中执行一些计算。进一步假设一旦这些计算完成,需要在线程开始其循环的新迭代之前对结果进行一些处理。

 

看以下示例代码(摘自cppreference):

 

#include <barrier>

#include <iostream>

#include <string>

#include <thread>

#include <vector>

  

int main() {

  const auto workers = { "anil", "busara", "carl" };

  

  auto on_completion = []() noexcept {  

    // locking not needed here

    static auto phase = "... done\n" "Cleaning up...\n";

    std::cout << phase;

    phase = "... done\n";

  };

  std::barrier sync_point(std::ssize(workers), on_completion);

  

  auto work = [&](std::string name) {

    std::string product = "  " + name + " worked\n";

    std::cout << product;  // ok, op<< call is atomic

    sync_point.arrive_and_wait();

  

    product = "  " + name + " cleaned\n";

    std::cout << product;

    sync_point.arrive_and_wait();

  };

  

  std::cout << "Starting...\n";

  std::vector<std::thread> threads;

  for (auto const& worker : workers) {

    threads.emplace_back(work, worker);

  }

  for (auto& thread : threads) {

    thread.join();

  }

}

可能的输出如下:

 

Starting...

  anil worked

  carl worked

  busara worked

... done

Cleaning up...

  busara cleaned

  carl cleaned

  anil cleaned

... done

semaphore

信号量,这个估计大家都很熟悉,本质也是个计数器,主要有两个方法:

 

acquire():递减计数器,当计数器为零时阻塞,直到计数器再次递增。

 

release():递增计数器(可传递具体数字),并解除在acquire调用中的线程的阻塞。

 

示例代码如下:

 

#include <iostream>

#include <thread>

#include <chrono>

#include <semaphore>

 

std::binary_semaphore

  smphSignalMainToThread(0),

  smphSignalThreadToMain(0);

  

void ThreadProc() {   

  smphSignalMainToThread.acquire();

  std::cout << "[thread] Got the signal\n"; // response message

  using namespace std::literals;

  std::this_thread::sleep_for(3s);

  

  std::cout << "[thread] Send the signal\n"; // message

  smphSignalThreadToMain.release();

}

  

int main() {

  std::thread thrWorker(ThreadProc);

  std::cout << "[main] Send the signal\n"; // message

  

  smphSignalMainToThread.release();

  

  smphSignalThreadToMain.acquire();

  

  std::cout << "[main] Got the signal\n"; // response message

  thrWorker.join();

}

输出如下:

[main] Send the signal

[thread] Got the signal

[thread] Send the signal

[main] Got the signal

信号量也可以当作条件变量使用,这个我估计大家应该知道怎么做。


我是小职,记得找我

✅ 解锁高薪工作

✅ 免费获取基础课程·答疑解惑·职业测评

C++入门到精通-C++20新特性的小细节

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程