爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      【C++11】线程库

      首页 知识中心 软件开发 文章详情页

      【C++11】线程库

      2024-05-29 08:28:31 阅读次数:44

      c++,开发语言

       

      thread 线程库

      在C++11之前,涉及到多线程问题,都是和平台相关的,比如Windows和Linux下各有自己的接口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。要使用标准库中的线程,必须包含< thread >头文件。

      【C++11】线程库

      thread类中的接口如下:

      构造函数:

      【C++11】线程库

      • 支持无参构造,即构造一个空线程对象,由于该线程对象不会和任何外部线程关联,也没有关联的线程函数,因此不能直接开始执行线程,无参构造通常需要配合移动赋值来使用。
      • 支持构造一个线程对象,并关联线程函数,构造函数中的可变参数是传递给线程函数的参数,这种线程对象一旦创建就会开始执行。同时支持移动构造,即使用一个将亡对象来构造一个新的线程对象。

      赋值重载:

      【C++11】线程库

      • 线程不允许两个非将亡对象之间的赋值,只允许将一个将亡对象赋值给另一个非将亡对象,即移动赋值,移动赋值的最常见用法是构造一个匿名线程对象,然后将其赋值给一个空线程对象。

      其他相关接口:

      【C++11】线程库

      • get_id: 获取当前线程的id,即线程的唯一标识——bool joinable() const noexcept。
      • joinable: 用于检查当前线程对象是否与某个底层线程相关联,从而判断是否需要对线程对象进行join() 或者 detach 操作——bool joinable() const noexcept。
      • join: 由于线程是进程中的一个执行单元,同时线程的所有资源也是有进程分配的,所以主线程在结束之前需要对其他从线程进行join。即判断从线程是否全部执行完毕,如果执行完毕,就回收从线程资源并继续向后执行。如果存在未执行完毕的从线程,主线程就会阻塞在join语句处等待从线程,直到所有从线程都执行完毕——void join()。
      • detach: 将当前线程与主线程分离,分离后主线程不能再join当前线程。当前线程的资源会被自动回收——void detach()。

      thread使用注意事项:

      1. 线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的状态。当创建一个线程对象后,没有提供线程函数,该对象实际没有对应任何线程。
        【C++11】线程库
      2. 当创建一个线程对象后,并且给线程关联线程函数,该线程就被启动,与主线程一起运行。线程函数一般情况下可按照 函数指针、lambda表达式和函数对象 三种方式提供。在这里说明一下:lambda表达式的本质其实是匿名的函数对象。
        【C++11】线程库
        由于创建线程时,这些线程的执行顺序完全是由操作系统来进行调度的,因此thread 1/2/3 的输出顺序也是不确定的。
      3. 我们可以通过joinable() 函数来判断线程是否有效,如果是以下几种情况。则线程无效:采用无参构造函数构造的线程对象、线程对象的状态已经转移给其他线程对象、线程已经调用join或者detach结束。
      4. 线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的,因此即使线程参数为引用类型,在线程中修改后也不能修改外部实参。因为实际引用的是线程栈中的拷贝,而不是外部的实参。
        【C++11】线程库
        【C++11】线程库
      5. 进程具有独立性,所以一个进程的退出并不会影响其他进程的正常运行。但是线程并不是独立的,一个进程下的多个线程共享进程的地址空间,所以一个线程的奔溃会导致整个进程奔溃。

      this_thread 命名空间

      C++11thread 头文件中,除了有thread类,还存在一个this_thread命名空间,它保存了线程的一些相关属性。

      yield 函数

      【C++11】线程库

      sleep_for 函数

      【C++11】线程库

      面试题:并行和并发的区别?

      并发和并行都是指多个任务同时执行的情况,但是它们的含义有所不同。

      • 并发是指在同一个时间段内,多个任务交替地执行,这些任务可以在同一台计算机上运行,也可以在不同的计算机上运行,彼此之间通过网络或其他方式进行通信和同步。并发常常用来提高系统的吞吐量和响应性,以及实现资源共享和负载均衡等功能。

      • 而并行是指在同一个时间点上,多个任务同时执行,这些任务通常在多个处理器或多个计算机上运行,每个任务分配给不同的处理器或计算机进行处理。并行常常用来加速计算和处理速度,提高系统的性能。


      mutex 锁

      C++11 中引入了一个新的 mutex 类,mutex是一个可锁定对象,它用于在多个线程之间锁定共享资源以防止竞争条件。

      当我们对程序当中的某一部分代码加锁之后,线程如果想要执行这部分代码就必须先申请锁。当访问完毕后再释放锁,同时,一把锁在同一时间只能被一个线程持有,当其他线程再来申请锁时,会直接申请失败。从而阻塞或不断重新申请,直到持有锁的线程释放。通过以上策略,就能保证多个线程只能串行的访问临界区中的代码/数据,从而保证了线程安全问题。

      【C++11】线程库

      mutex 的主要接口如下:

      • 构造: 互斥锁仅支持无参构造,不支持拷贝构造
        【C++11】线程库
      • lock: 加锁函数。如果当前锁没有被任何线程持有,则当前线程持有锁并加锁,如果当前锁已经被其他线程持有,则当前线程阻塞直到持有锁的线程释放锁,如果当前互斥量被当前调用线程锁住,则会产生死锁。
      • try_lock: 尝试加锁函数。如果当前锁没有被任何线程持有,则当前线程持有锁并加锁。如果当前锁已经被其他线程持有,则加锁失败返回false,但当前线程并不会阻塞,而是跳过临界区代码继续向后执行。如果当前互斥量被当前调用线程锁住,则会产生死锁。
      • unlock: 解锁函数。当前线程执行完毕临界区中的代码后释放锁。如果存在其他线程正在申请当前锁,则它们其中一个将会持有锁并继续向后执行。当前锁也可能重新被当前线程竞争得到。
      int x = 0;
      mutex mtx;
      void Func(int n)
      {
      	for (int i = 0; i < n; i++) {
      		mtx.lock();
      		++x;
      		mtx.unlock();
      	}
      }
      

      【C++11】线程库

      在这个示例中,我们创建了两个线程 t1 和 t2,它们都要修改全局变量x。这里我们使用了一把全局互斥锁来保护共享变量x,保护x不会被多个线程同时访问。

      关于 lock_guard

      lock_guard 是一种用于管理互斥锁的 RAII(Resource Acquisition Is Initialization)类。它可以保证在作用域结束时自动释放互斥锁,以避免忘记手动释放锁所导致的问题。

      使用 lock_guard 类可以避免手动管理互斥锁的问题,可以提高程序的可读性和可维护性。在创建 lock_guard 对象时,需要传入一个互斥锁对象,这个互斥锁对象会被 lock_guard 类包装,当 lock_guard 对象被销毁时,它会自动调用互斥锁对象的 unlock 函数,释放互斥锁。

      lock_guard 类的使用非常简单,只需要在需要使用互斥锁的代码块中创建一个 lock_guard 对象即可,不需要手动加锁和解锁。当程序流程离开这个代码块时,lock_guard 对象会自动释放互斥锁。由于 lock_guard 对象的生命周期是由编译器控制的,因此无论代码流程中出现何种异常情况,lock_guard 对象都会在作用域结束时被自动销毁,从而保证了程序的正确性。

      lock_guard的模拟实现

      template <class Lock>
      class LockGuard
      {
      public:
      	LockGuard(Lock& lock)
      		: _lock(lock)
      	{
      		_lock.lock();
      	}
      
      	~LockGuard()
      	{
      		_lock.unlock();
      	}
      	
      	LockGuard(const LockGuard&) = delete;
      	LockGuard& operator=(const LockGuard&) = delete;
      
      private:
      	Lock& _lock;
      };
      

      LockGuard的使用

      int x = 0;
      mutex mtx;
      void Func(int n)
      {
      	for (int i = 0; i < n; i++)
      	{
      		try
      		{
      			LockGuard<mutex> lock(mtx);
      			++x;
      
      			// 抛异常
      			if (rand() % 3 == 0)
      			{
      				throw exception("抛异常");
      			}
      		}
      		catch (const std::exception& e)
      		{
      			cout << e.what() << endl;
      		}
      	}
      }
      

      【C++11】线程库

      在 C++11 线程库中,线程执行例程的参数可以是引用也可以是拷贝,具体取决于用户如何传递参数。如果将参数作为值传递,则会进行拷贝构造,而如果将参数作为引用传递,则不会进行拷贝构造。

      如果需要真正实现传递引用,可以使用 std::ref 函数将引用类型的参数包装成 std::reference_wrapper 类型的对象,然后将这个对象作为参数传递给线程的执行例程。 std::reference_wrapper 是一个模板类,它提供了一种引用的包装方式,可以像普通对象一样进行拷贝和赋值,同时可以通过调用其 get 函数获取其包装的引用。

      如果有一个函数需要传递一个引用类型的参数,可以使用 ref 函数将这个引用包装成 reference_wrapper 类型的对象,并将其作为参数传递给线程的执行例程。

      注:线程构造函数的参数包并不是直接传给执行例程的,而是先用参数包的参数去构造线程,然后再将这些参数传递给线程的执行例程。互斥锁没有被识别成引用传递的问题是出现在构造线程时参数包传递的过程。线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的,因此:即使线程参数为引用类型,在线程中修改后也不能修改外部实参,因为其实际引用的是线程栈中的拷贝,而不是外部实参。

      unique_lock

      与 lock_guard 类似,unique_lock 类模板也是采用 RAII 的方式对锁进行了封装,并且也是以独占所有权的方式来管理 mutex 对象的上锁和解锁操作,即其对象之间不能发生拷贝。

      与 lock_guard 不同的是,unique_lock 更加的灵活,提供了更多的成员函数:

      • 上锁/解锁操作:lock、try_lock、try_lock_for、try_lock_until 和 unlock。
      • 修改操作:移动赋值、交换 (swap:与另一个unique_lock对象互换所管理的互斥量所有权)、释放 (release:返回它所管理的互斥量对象的指针,并释放所有权)。
      • 获取属性:owns_lock (返回当前对象是否上了锁)、operator bool() (与 owns_lock() 的功能相同)、mutex (返回当前 unique_lock 所管理的互斥量的指针)。

      unique_lock 和 lock_guard 最大的区别在于 lock_guard 无法手动释放和重新获取互斥锁,只能在创建时 lock,析构时 unlock,这在某些复杂的多线程编程场景中可能会受到一些限制。而 unique_lock 则提供了更加灵活和精细的互斥锁控制,unique_lock 可以在任何时刻手动地释放和重新获取互斥锁,并且支持不同的互斥锁处理策略,例如延时加锁、尝试加锁等。


      std::recursive_mutex

      recursive_mutex允许同一个线程对互斥量多次上锁(即递归上锁),来获得对互斥量对象的多层所有权,释放互斥量时需要调用与该锁层次深度相同次数的 unlock,除此之外,recursive_mutex 的特性和 mutex 大致相同。

      std::timed_mutex

      比 std::mutex 多了两个成员函数,try_lock_for 和 try_lock_until。

      • try_lock_for:接受一个时间范围,表示在这一段时间范围之内线程如果没有获得锁则被阻塞住(与 mutex 的 try_lock 不同,try_lock 如果被调用时没有获得锁则直接返回 false),如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。
      • try_lock_until:接受一个时间点作为参数,在指定时间点未到来之前线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。

      这里我们需要注意的是,在实际开发中try_lock_for() 和 try_lock_until()并不常用,其中对于时间的控制也比较复杂,因此这里我们只需要了解即可。

      【C++11】线程库

      这里我们可以看到,当前的这种情况下,在整个for循环的外面加锁的效率会更高,这是因为整个CPU的速度很快,如果我们对++x进行加锁,那么CPU就会频繁的在t1和t2两个线程之间切换,并且t1和t2也需要频繁的加锁和解锁,而这些操作都是要消耗资源的。

      【C++11】线程库


      atomic 原子性操作

      虽然我们可以通过加锁来对共享资源进行保护,但加锁存在一定的缺陷,比如多个线程只能串行访问被锁包含的资源,会导致程序的运行效率降低。同时,加锁不当还会导致死锁的问题。因此C++11引入了原子性操作。原子操作不可被中断的一个或一系列操作,C++11通过引入原子操作类型,使得线程间数据的同步变得更加高效。

      【C++11】线程库

      由于原子类型通常属于资源型数据,多个线程只能访问单个原子类型的拷贝,因此在C++11中,原子类型只能从其模板参数中进行构造,不允许原子类型进行拷贝构造、移动构造以及赋值重载等。

      【C++11】线程库

      atomic类 主要支持原子性的 ++、--、+、-、按位与、按位或以及按位异或操作。

      atomic类能够支持这些原子性操作本质是因为其底层对CAS操作进行了封装,可以简单的理解为 atomic = CAS + while。


      CAS 操作

      CAS (compare and swap) 是 CPU 硬件同步原语,它是支持并发的第一个处理器提供原子的测试并设置操作。CAS 操作包含三个操作数 – 内存位置(V)、预期原值(A)和新值 (B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则处理器不做任何操作。

      我们还是以 ++g_val 操作为例,和一般的 ++ 操作不同,CAS 在会额外使用一个寄存器来保存讲寄存器中 g_val 修改之前的值 (预期原值),并且在将修改之后的值 (新值) 写回到内存时会重新取出内存中 g_val 的值与预期原值进行比较,如果二者相等,则将新值写入内存;如果二者不等,则放弃写入。

      这样当线程 A 将新值写入到内存之前,如果有其他线程对 g_val 的值进行了修改,则内存中 g_val 的值就会与预期原值不等,此时操作系统就会放弃写入来保证整个 ++ 操作的原子性。

      但单纯的放弃写入会导致可能当前 ++ 操作执行了但是 g_val 的值并不变;所以 C++ 对 CAS 操作进行了封装,即在 CAS 外面套了一层 while 循环,当新值成功写入时跳出循环,当新值写入失败时重新执行之前的取数据、修改数据、写回数据的操作,直到新值写入成功。这样做的优点是即实现了语言层面上 ++ 操作的原子性,解决了其线程安全问题;缺点是有一些 ++ 操作可能要重复执行多次才能成功,一定程度上影响程序效率,但还是比加锁解锁的效率要高。

      注: 上面只是对 atomic 底层原理的简单理解,atomic 底层逻辑控制肯定不是单纯的 CAS + while 这么简单的,但作为一般程序员这样理解也就够了。感兴趣的可以看一下陈皓大佬的这一篇文章 无锁队列的实现。

      int main()
      {
      	int n = 100000;
      
      	atomic<int> x = 0;
      	thread t1([&, n](){
      		for (int i = 0; i < n; i++)
      		{
      			++x;
      		}
      	});
      
      	thread t2([&, n]() {
      			for (int i = 0; i < n; i++)
      			{
      				++x;
      			}
      		});
      
      	t1.join();
      	t2.join();
      	size_t end = clock();
      
      	printf("%d\n", x.load());
      	return 0;
      }
      

      【C++11】线程库


      condition_variable 条件变量

      C++11 中的 condition_variable 是用于 线程同步 的一种机制,它能够协调多个线程之间的操作,以便它们能够有效地进行通信和同步。

      condition_variable 通常与互斥锁一起使用,用于实现生产者-消费者模型、读者-写者模型等线程间同步的场景。

      condition_variable 提供了两个主要的操作:wait 和 notify_one 或 notify_all。

      • wait 操作会使当前线程阻塞,并释放关联的互斥锁,直到另外一个线程调用了 notify_one 或 notify_all 方法,通知该线程可以继续执行了。

      • notify_one 操作会唤醒一个正在等待的线程,而notify_all 操作会唤醒所有正在等待的线程。如果没有线程处于等待状态,则这两个函数不会产生任何影响。

      wait函数提供了两个不同版本的接口:

      【C++11】线程库

      • 调用第一个版本的wait函数时只需要传入一个互斥锁,线程调用wait后会立即被阻塞,直到被唤醒。

      • 调用第二个版本的wait函数时除了需要传入一个互斥锁,还需要传入一个返回值类型为bool的可调用对象,与第一个版本的wait不同的是,当线程被唤醒后还需要调用传入的可调用对象,如果可调用对象的返回值为false,那么该线程还需要继续被阻塞。

      为什么调用wait系列函数时需要传入一个互斥锁?

      1. 因为wait系列函数一般是在临界区中调用的,为了让当前线程调用wait阻塞时其他线程能够获取到锁,因此调用wait系列函数时需要传入一个互斥锁,当线程被阻塞时这个互斥锁会被自动解锁,而当这个线程被唤醒时,又会自动获得这个互斥锁。

      2. 因此wait系列函数实际上有两个功能,一个是让线程在条件不满足时进行阻塞等待,另一个是让线程将对应的互斥锁进行解锁。

      注意:调用wait系列的函数时,传入互斥锁的类型必须是unique_lock。条件变量下,可能会有多个线程正在进行阻塞等待,这些线程会被放到一个等待队列中进行排队。


      实现两个线程交替打印1-100

      尝试用两个线程交替打印1-100的数字,要求一个线程打印奇数,一个线程打印偶数,并且打印数字从小到大依次递增。

      该题目主要考察的就是线程的同步和互斥。

      • 互斥:两个线程都在向控制台打印数据,为了保证两个线程的打印数据不会相互影响,因此需要对线程的打印过程进行加锁保护。
      • 同步:两个线程必须交替进行打印,因此需要用到条件变量让两个线程进行同步,当一个线程打印完再唤醒另一个线程进行打印。

      但如果只有同步和互斥是无法满足题目要求的。

      1. 首先,我们无法保证哪一个线程会先进行打印,不能说先创建的线程就一定先打印,后创建的线程先打印也是有可能的。
      2. 此外,有可能会出现某个线程连续多次打印的情况,比如线程1先创建并打印了一个数字,当线程1准备打印第二个数字的时候线程2可能还没有创建出来,或是线程2还没有在互斥锁上进行等待,这时线程1就会再次获取到锁进行打印。
      int main()
      {
      	mutex mtx;
      	condition_variable cv;
      
      	int n = 100;
      	int x = 1;
      
      	thread t1([&, n]() {
      		while (x < 100)
      		{
      			unique_lock<mutex> lock(mtx);
      			if (x >= 100) break;
      			if (x % 2 == 0) { // 偶数就阻塞
      				cv.wait(lock);
      			}
      			cout << "线程" << this_thread::get_id() << ":" << x << endl;
      			++x;
      			cv.notify_one();
      		}
      		});
      
      	thread t2([&, n]() {
      		while (x < 100)
      		{
      			unique_lock<mutex> lock(mtx);
      			if (x > 100) break;
      			if (x % 2 != 0) { // 奇数就阻塞
      				cv.wait(lock);
      			}
      			cout << "线程" << this_thread::get_id() << ":" << x << endl;
      			++x;
      			cv.notify_one();
      		}
      		});
      
      	t1.join();
      	t2.join();
      
      	return 0;
      }
      

      【C++11】线程库


      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://chenjiale.blog.csdn.net/article/details/134386095,作者:星河万里᭄ꦿ࿐,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:增加PHP性能分析

      下一篇:【C++】C++11——右值引用和移动语义|可变参数模板

      相关文章

      2025-05-19 09:04:53

      查看RISC-V版本的gcc中默认定义的宏

      查看RISC-V版本的gcc中默认定义的宏

      2025-05-19 09:04:53
      c++ , linux
      2025-04-14 09:26:51

      【算法入门08】青蛙跳台阶

      【算法入门08】青蛙跳台阶

      2025-04-14 09:26:51
      c++ , 动态规划 , 算法
      2025-04-14 09:26:51

      STL详解(九)—— priority_queue的使用与模拟实现

      优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。

      2025-04-14 09:26:51
      c++ , stl , 数据结构
      2025-04-14 09:26:51

      STL详解(八)—— stack和queue的模拟实现

      stack和queue有一点需要注意的是,虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和queue只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque容器。

      2025-04-14 09:26:51
      c++ , queue , stack , stl
      2025-04-14 09:24:23

      【算法入门14】二叉树的镜像

      【算法入门14】二叉树的镜像

      2025-04-14 09:24:23
      c++ , 算法
      2025-04-14 09:24:23

      【算法入门09】矩形覆盖

      【算法入门09】矩形覆盖

      2025-04-14 09:24:23
      c++ , 动态规划 , 算法
      2025-04-07 10:28:48

      Python高维统计建模变量选择:SCAD平滑剪切绝对偏差惩罚、Lasso惩罚函数比较

      变量选择是高维统计建模的重要组成部分。许多流行的变量选择方法,例如 LASSO,都存在偏差。

      2025-04-07 10:28:48
      python , r语言 , 后端 , 开发语言
      2025-04-07 10:20:39

      ​Python是如何表示时间的?2个模块、3种方式,1文看懂~

      ​Python是如何表示时间的?2个模块、3种方式,1文看懂~

      2025-04-07 10:20:39
      python , 开发语言 , 时间戳 , 结构化
      2025-04-01 10:29:12

      golang与 C++数据结构类型对应关系是怎样的?

      uintptr和unsafe.Pointer相当于c++的void*,也就是任意指针。

      2025-04-01 10:29:12
      c++ , golang , 函数指针 , 数据结构
      2025-04-01 10:28:37

      找到非负数组中拥有“最大或的结果“的最短子数组,返回最短长度。

      找到非负数组中拥有"最大或的结果"的最短子数组,返回最短长度。

      2025-04-01 10:28:37
      java代码 , rust , 后端 , 开发语言 , 数组
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5266969

      查看更多

      最新文章

      Python高维统计建模变量选择:SCAD平滑剪切绝对偏差惩罚、Lasso惩罚函数比较

      2025-04-07 10:28:48

      ​Python是如何表示时间的?2个模块、3种方式,1文看懂~

      2025-04-07 10:20:39

      golang与 C++数据结构类型对应关系是怎样的?

      2025-04-01 10:29:12

      找到非负数组中拥有“最大或的结果“的最短子数组,返回最短长度。

      2025-04-01 10:28:37

      【C语言】探索数据的存储(上篇)

      2025-04-01 09:21:49

      MFC编程 -- 判断是否按下ctrl和shift键

      2025-03-31 08:49:25

      查看更多

      热门文章

      Lambda函数

      2023-02-08 10:33:56

      QT中多线程的使用

      2023-02-07 10:34:04

      0030 简单的四则运算 c/c++

      2023-03-21 10:39:47

      C++虚函数知识点总结

      2023-02-21 06:21:46

      (10)Qt对象模型

      2023-02-13 07:55:59

      java学习第三天笔记-运算符10-短路逻辑运算符56

      2023-04-07 06:41:50

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      整数数组 stations 表示 水平数轴 上各个加油站的位置。

      总长度为n的数组中,所有长度为k的子序列里,有多少子序列的和为偶数?

      java synchronized 锁住同一个类的静态方法和非静态方法会互斥吗?

      Python __str__() 方法

      项目代码规范(代码标准化、C++、Python)

      C++系列五:输入/输出

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号