目录

简介

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

与进程进程相比,其所需的资源更少,线程之间沟通的方法更多; 他们之间的区别可以比较简明用以下几点概括[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. 无所不能的Embedding5 - skip-thought的兄弟们[Trim/CNN-LSTM/quick-thought]

    这一章我们来聊聊skip-thought的三兄弟,它们在解决skip-thought遗留问题上做出了不同的尝试[Ref1-4], 以下paper可能没有给出最优的解决方案(对不同的NLP任务其实没有最 ...

  2. PyQt学习随笔:自定义信号连接时报AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 如果使用自定义信号,一定要记得信号是类变量,必须在类中定义,不能在实例 ...

  3. PyQt(Python+Qt)学习随笔:QColumnView的resizeGripsVisible属性

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QColumnView在一个视图中展示多个列表,每个下级列表是上一个列表的数据项的分支, QColu ...

  4. XFF SSTI 模板注入 [BJDCTF2020]The mystery of ip

    转自https://www.cnblogs.com/wangtanzhi/p/12328083.html SSTI模板注入:之前也写过:https://www.cnblogs.com/wangtanz ...

  5. centos7.5以上poenssl和openssh升级

    2020年12月09日,360CERT监测发现  openssl  发布了  openssl 拒绝服务漏洞  的风险通告,该漏洞编号为  CVE-2020-1971  ,漏洞等级:高危 ,漏洞评分:7 ...

  6. 题解-CF1282E The Cake Is a Lie

    题面 CF1282E The Cake Is a Lie \(T\) 组测试数据.每次给一个 \(n\) 边形的三角剖分,求节点顺序和剖分顺序. 数据范围:\(3\le n\le 10^5\),\(\ ...

  7. 基数排序(Radix Sort)

    基数排序(Radix Sort) 第一趟:个位 收集: 第二趟:十位 第三趟:百位 3元组 基数排序--不是基于"比较"的排序算法 递增就是把收集的过程返过来 算法效率分析 需要r ...

  8. Object not found! The requested URL was not found on this server.... 报错解决方案

    服务器(centos6.5) lnmp 报错如下 Object not found! The requested URL was not found on this server. The link ...

  9. Elastic Search 学习之路(一)

    一.基本概念及缘由 1.Sql vs nosql SQL:Structured Query Language Nosql:Not only SQL Relationship DB Relations: ...

  10. springmvc中使用文件上传功能

    项目代码:https://github.com/PeiranZhang/springmvc-fileupload Servlet3.0之前使用文件上传功能 Servlet3.0之前需要使用common ...