目录

简介

本文主要介绍了标准库中的线程部分。线程是目前多核编程里面最重要的一部分。

与进程进程相比,其所需的资源更少,线程之间沟通的方法更多; 他们之间的区别可以比较简明用以下几点概括[1]:

  1. 进程是资源分配的最小单位,线程是CPU调度的最小单位;也就是说进程之间的资源是相互隔离,而线程之间的是可以相互访问的。
  2. 线程的存在依赖于进程,一个进程可以保护多个线程;
  3. 进程出现错误不会影响其他进程,但是一个线程出现错误,会影响同一进程下的所有线程。

线程的使用

线程的创建

一般使用std::thread创建一个线程。std::thread支持输入一个函数对象,及一些参数,类似于std::bind,不过没有占位符。

最常见,最简单的是对输入一个匿名函数作为参数:

std::thread t1([]() {
std::cout << "Hello World" << std::endl;
});
t1.join();

结果如下:

需要注意的是,在使用多线程的时候,如果使用类似于std::cout << "Hello World" << std::endl;的语句,容易造成输出的混乱。比如

std::thread t1([]() {
std::cout << "Hello World1" << std::endl;
});
std::thread t2([]() {
std::cout << "Hello World2" << std::endl;
});
t1.join();
t2.join();

以上代码,我们一般来说期望的输出是

但是,在一些情况下,它还会以以下的方法输出

造成这个的原因很简单,因为"Hello World"std::endl的输出是分开的,所以他们之间可能被插入其他的输出。为了解决这个问题。一般会使用一个完整的字符串进行输出,但是C++在格式化这一方面做的比较差(C++20format库看起来还不错),所以一般情况下会使用printf输出。

线程的方法和属性

  1. joinable()判断线程是否可连接(可执行线程)的,有以下情况的,为不可连接的:

    1. 构造时,thread()没有参数;
    2. 该对象的线程已经被移动了;
    3. 该线程已经被joindetach
  2. get_id() 返回线程的ID;

  3. native_handle() 返回POSIX标准的线程对象;

  4. join() 等待线程执行完成;

  5. detach() 分离线程,分离后对象不再拥有线程。该线程结束后,会自动回收内存。(并不会开启另一个进程);

  6. swap() 交换对象的线程。

std::jthread (C++20)

除了常用的std::thread外,标准库还存在着另一个可以创建线程的类,std::jthread。他们之间的差别比较明显的就是,std::jthread会在解构的时候判断线程是否还在运行joinable,如果还在运行则自动调用request_stopjoin

除此之外,std::jthread还提供了一个内置的std::stop_token。可以通过线程函数的第一个参数来获取(如果函数的第一个参数类型为std::stop_token)。

可以通过get_stop_sourceget_stop_tokenrequest_stop等方法来对其进行操作。

stop_token (C++20)

stop_token类似于一个信号,告诉线程是否到了结束的时候。和stop_source一起使用。stop_token用来获取是否退出(读),而stop_source用来请求推出(读写)。其方法:

  1. request_stop 请求退出

  2. stop_requested 获取是否已经请求退出

  3. stop_possible 获取是否可以请求退出

样例:

void thread_func(std::stop_token token) {
int data = 0;
while (!token.stop_requested()) {
printf("%d\n", data);
data++;
std::this_thread::sleep_for(1s);
}
printf("Exit\n");
} int main() {
std::jthread mythread(thread_func); std::this_thread::sleep_for(4s); return 0;
}

输出:

总结

本次讲述了线程创建的一些方法,可以看到相比较C语言而言,由于C++11提出的函数对象(普通函数、匿名函数,std::bind的输出等)使得线程的创建更加的方便。

下一次将讲述线程之间的通信。在C++中,线程之间的通信方法和C语言提供的类似,不过是将其包装了一下。

Ref

[1] https://www.zhihu.com/question/25532384

博客原文:https://www.cnblogs.com/ink19/p/std_thread-1.html

std::thread线程详解(1)的更多相关文章

  1. std::thread线程库详解(2)

    目录 目录 简介 最基本的锁 std::mutex 使用 方法和属性 递归锁 std::recursive_mutex 共享锁 std::shared_mutex (C++17) 带超时的锁 总结 简 ...

  2. Java线程创建形式 Thread构造详解 多线程中篇(五)

    Thread作为线程的抽象,Thread的实例用于描述线程,对线程的操纵,就是对Thread实例对象的管理与控制. 创建一个线程这个问题,也就转换为如何构造一个正确的Thread对象. 构造方法列表 ...

  3. 通用线程:POSIX 线程详解,第 3 部分 条件互斥量(pthread_cond_t)

    使用条件变量提高效率 本文是 POSIX 线程三部曲系列的最后一部分,Daniel 将详细讨论如何使用条件变量.条件变量是 POSIX 线程结构,可以让您在遇到某些条件时“唤醒”线程.可以将它们看作是 ...

  4. Java基础-进程与线程之Thread类详解

    Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...

  5. python线程详解

    #线程状态 #线程同步(锁)#多线程的优势在于可以同时运行多个任务,至少感觉起来是这样,但是当线程需要共享数据时,可能存在数据不同步的问题. #threading模块#常用方法:'''threadin ...

  6. Thread.setDaemon详解

    Thread.setDaemon详解 线程分为两种类型:用户线程和守护线程.通过Thread.setDaemon(false)设置为用户线程:通过Thread.setDaemon(true)设置为守护 ...

  7. 通用线程:POSIX 线程详解,第 3 部分

    通用线程:POSIX 线程详解,第 3 部分 使用条件变量提高效率 Daniel Robbins, 总裁兼 CEO, Gentoo Technologies, Inc. 简介: 本文是 POSIX 线 ...

  8. POSIX 线程详解(经典必看)

    http://www.cnblogs.com/sunminmin/p/4479952.html 总共三部分: 第一部分:POSIX 线程详解                               ...

  9. java.lang.Thread类详解

    java.lang.Thread类详解 一.前言 位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前 ...

随机推荐

  1. 本地eclipse java api连接远程虚拟机HBase

    1.本地与远程连通 无论是域名或者ip都可以,另外需保证HBase在虚拟机集群上正常运行. 2.本地要有一个跟远程相同的hadoop环境 当然不相同,只要兼容也可以,现采用hadoop-2.5.0-c ...

  2. Python函数独立星号(*)分隔的命名关键字参数

    如果需要限制关键字参数的输入名字,就需要使用到命名关键字参数的形式,所谓命名关键字参数就是给关键字参数限定指定的名字,输入其他名字不能识别.命名关键字参数和位置参数之间使用独立的星号(*)分隔,星号后 ...

  3. 【JAVA】SSM开源项目源码--城市学院移动后勤-毕业设计(Spring SpringMvc Mybatis Mui Redis )

    项目简介 大学时期老师给我做的项目,学校后勤管理中心,也作为毕业设计项目. 有 后勤保修 二手交易 失物招领 后勤通知 等功能. 城市学院移动后勤 有APP端(webapp)和WEB端(PC) 后端使 ...

  4. XPATH基本语法

    1.XPATH与自动化之间的关系 1.XPATH是一门在XML文档中查找信息的语言.XPATH可用来在XML文档中对元素和属性进行遍历. 2.XPATH是用来选择"节点"的一种基于 ...

  5. MySQL入门看这一篇就够了

    MySQL JavaEE:企业级Java开发 web阶段 分为1.前端(页面,展示数据库中的数据) 2.后台(连接点:链接数据库JDBC.Mybatis,链接前端(控制视图跳转,给前端传递数据)) 3 ...

  6. vue 中 this.$options.data() 重置

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. Java并发编程的艺术(四)——JMM、重排序、happens-before

    什么是JMM JMM就是Java内存模型.目的是为了屏蔽系统和硬件的差异,让同一代码在不同平台下能够达到相同的访问结果.规定了线程和内存之间的关系. 内存划分 JMM规定了内存主要划分为主内存和工作内 ...

  8. 如何写好商用PPT,计算机行业PPT模板

    如何写好商用PPT,这个问题如果从0开始写那确实需要花费一番功夫,今天我不是来教你如何做PPT,而是教你如何从一个小白如何快速能套用模板,从而做出一个自己行业相关的模板,比如计算机行业PPT模板,奶茶 ...

  9. jvm基本结构和解析

    jvm的基本结构图如下 这只是代表我的个人理解  不是很深刻  欢迎各类大神进行补充和纠正 jvm之所以强大就是因为他从软件层面屏蔽不用操作系统在底层硬件与指令上的区别,从而可以在不同系统上兼容 主要 ...

  10. 六个步骤,从零开始教你搭建基于WordPress的个人博客

    摘要:WordPress是使用PHP语言开发的博客平台,是免费开源的.用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站,也可以把WordPress当作一个内容管理系统(CMS)来使用 ...