创建线程 接收 com组件的回调函数_简明modern C++多线程系列教程 - 1. 引言

Simplicity is the Ultimate Sophistication --Leonardo da Vinci.

Overview

无论是服务端编程, 云计算. 并行程序设计已经成为了一个合格的程序员必须掌握的技能之一. 而C++作为一门偏底层的高级编程语言, 从C++入手学习多线程更有助于初学者打好坚实的基础. 自从C++ 11发布以来, 多线程开发变得标准化了, 这意味着C++多线程编程代码可以不再依赖与特定的平台即POSIX 和 windows API可以沿用一套代码, 极大的促进了编程效率.

首先先来看C++到底提供了哪些供与并发编程的组件

27a25d87cb2262ef63b81fb5e72c7931.png

可见, C++对多线程编程的支持越来越多, 但核心部分和其他多线程编程是类似的, 咱们先来回顾以下基础也是核心的概念:

Thread/process

之前面试经常被问及进程和线程有什么不同, 一般标答会这样答: 进程是系统进行资源分配和调度的一个独立单位, 线程CPU调度和分派的基本单位. 之后列举不同点, 如有共享地址空间的区别, 占用文件描述符等资源区别等等, 最后在提一下两者的从属关系. 其实这些话都可以用对硬件的抽象来概括: 进程是内存的抽象, 线程是CPU的抽象. 是硬件的目的决定进程/线程的本身的目的, 笔者认为从这个角度能更加本质的理解为什么这两个抽象不同.

就C++来说, 线程往往可callable unit有关, 什么是callable unit: 1. 函数指针; 2.函数对象, 也就是通过重载operator()的struct/class; 3. lambda function. 线程的创建者会将callable unit作为线程的构造函数的输入, 并且具有对期生命周期的控制权, 如进行对线程进行join(当前线程交出控制权新创建的线程, 等待被join的线程结束), detach(创建出来的线程与当前线程脱离, 成为后台运行的线程). 一旦线程过了生命周期, thread的析构函数会调用std::terminate终止程序.

Shared Data

在线程调度的时候, 上下文切换是不可预期的, 因为此处的不确定性, 导致了同一段代码, 在多线程的环境操作共享数据的时候, 结果是不可预期的, 也叫做race condition, 那一段会导致race condition的代码被称为critical section. 因此我们需要提供一种协调机制, 使得代码在多线程的环境下, 执行顺序是可预期的.

Mutex

Luckily, mutex是用来在解决race condition的. 当我们在读/写变量的时候, 我们只允许一个线程对当前变量/内存进行读写, 在mutex保护的情况下, 若此时若发生了线程切换, 其他线程访问critical section由于当前已经有其他线程访问, 该线程得不到执行, 因此不会对shared data造成影响, 因此就实现了数据访问线程安全.

C++有不同的锁实现, 用于针对不同的应用场景, 比如运行同一个线程反复加锁, 尝试获取锁, 以及加上时间戳限制等等情况.

Locks/Guard

Locks/Guard主要是为了实现RAII原语, 一般来说, 一个线程加锁之后就需要负责将锁释放, 为了给程序员带来额外的负担, C++引入了包装类std::lock_guard, std::unique_lock, std::shared_lock来应对不同的情况

Conditional variables

Conditional variable是为了解决加锁后其他线程频繁检查锁, 白白耗费CPU时间片的缺陷. 其同步变量通过收发同步的消息来实现, 一个线程是信号发出者, 另一个是接收者; 信号发出者能够根据不同的信号block/wake up接收者.

Tasks

但是根据contional variable进行多个线程之间的消息传递会降低代码的可读性, 增加犯错的几率, C++提供了std::task机制, 能够自动化的异步处理两个对端协调和沟通的情况. 我们可以将task看成是一个数据通道, 一边发出std::promise, 一边接受std::future, 你可以在很多地方发现这种消息传递的影子, 即pipe; 正是这层额外的抽象, 大大方便了我们的编程

目录

回到开始, 本教程希望通过12篇左右简练但不简陋的系列博客介绍modern C++多线程编程相关的api, 内存模型, 和编程范式; 并且对leetcode 上多线程的题目, 对常见的C++多线程的面试编程题进行整理, 目前计划的话题如下:

  • 内存模型
    • atomic model and lock
    • callable object and thread
    • Fence
  • 编程范式
    • thread and related api
    • shared memory
    • Condition variable
    • Task
  • case study
    • leetcode 多线程习题
    • 线程安全的数据结构实现, 以vector为例
    • 线程安全的设计模式实现, 以singleton为例
  • 拾遗
    • C++ 20
    • 其他标准库组件: time lib

通该系列博客笔者觉得能够给读者们打好C++多线程的基础.

ps: 如果你觉得本文对你有帮助, 并且对之后的内容有所期待, 希望能获得你的赞, 欢迎指出任何错误与我理解不到位的地方, 期待和大家共同学习进步.

参考/推荐资料

该系列主要参考以下资料:

  1. https://www.modernescpp.com/index.php
  2. https://www.educative.io/courses/modern-cpp-concurrency-in-practice-get-the-most-out-of-any-machine
  3. C++ Concurrency in Action 2nd
  4. The C++ Standard Library, 2nd Edition
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值