目录

简介

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

与进程进程相比,其所需的资源更少,线程之间沟通的方法更多; 他们之间的区别可以比较简明用以下几点概括[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. 2020.11.30【NOIP提高A组】模拟赛反思

    90,rk42 T1 考试的时候觉得可以贪心,就每次找到最大的,然后以它为根去遍历每个子树,求出其最大值,然后删去这个点.一直持续直到边删完,时间复杂度\(O(n^2)\),然后想了想链的情况,没有打 ...

  2. moviepy音视频剪辑:headblur函数遇到的ValueError assignment destination is read-only问题及解决办法

    ☞ ░ 前往老猿Python博文目录 ░ 一.运行环境 运行环境如下: python版本:3.7 opencv-python版本:4.2.0.34 numpy版本:1.19.0 二.错误案例代码及报错 ...

  3. 第4.8节 三目运算、del和pass语句

    一.三目运算 Python的三目运算与C语言的三目运算非常类似,具体语法如下: 条件为真的赋值表达式   if  条件   else 条件为假的表达式 三目运算实际上就是一种表达式计算,当对应if后面 ...

  4. burp-requests插件安装使用

    这段时间都没更博客,扫描器的更新也暂时停止了,因为回了学校之后需要准备实验室招新和几个比赛的事情,内疚两秒钟,赶快学习! burp里面的插件很多,但是不要被纷繁复杂的功能迷了双眼,还是那句话:适合自己 ...

  5. STL-Vector容量问题:

    1.clear,erase ,pop_back() 函数只删除对象,并没有释放vec中的内存,若对象是指针还需要delete:2.在erase,clear,pop_back()删除对象的后,size改 ...

  6. nginx学习之——虚拟主机配置

    例子1: 基于域名的虚拟主机 server { listen 80;  #监听端口 server_name a.com; #监听域名 location / { root /var/www/a.com; ...

  7. 服务器ganglia安装(带有登录验证)

    1.ganglia组件gmond相当于agent端,主要手机各node的性能状态:gmetad相当于server端,从gmond以poll的方式收集和存储原数据:ganglia-web相当于一个web ...

  8. 使用纯js 不导包实现 table 导出 Excel

    1.将js粘贴到项目 2.设置table标签 id3.定义按钮,调用方法即可 1 <!DOCTYPE html> 2 <html lang="zh_CN"> ...

  9. STL——容器(Map & multimap)的简述与构造

    1. map/multimap 的简介 map 是标准的关联式容器,一个 map 里存储的元素是一个键值对序列,叫做 (key,value) 键值对.它提供基于 key 快速检索数据的能力. map ...

  10. Linux相关介绍和安装

    目录 前言 第一章 linux介绍 1.1 linux简介 第二章 Linux起源 2.1 Unix的历史 2.2 Unix操作系统的革命 2.3 Linux系统的诞生 2.4 Linux系统的发展史 ...