首页 > 编程语言 >c++ 多线程编程std::thread, std::shared_mutex, std::unique_lock

c++ 多线程编程std::thread, std::shared_mutex, std::unique_lock

时间:2023-03-31 11:35:56浏览次数:41  
标签:std 多线程 join thread 调用 mutex 线程 unique

在C++11新标准中,可以简单通过使用thread库,来管理多线程,使用时需要#include <thread>头文件。

简单用例如下:

1 std::thread(Simple_func);
2 std::thread t(Simple_func);
3 t.detach();

第一行是直接启动一个新线程来执行Simple_func函数,而第二行先声明一个线程函数t(返回类型为thread),然后用detach方法启动线程。

C++11有两种方式来等待线程结束:

  • detach方式,启动的线程自主在后台运行,当前的代码继续往下执行,不等待新线程结束。前面代码所使用的就是这种方式。
    • 调用detach表示thread对象和其表示的线程完全分离;
    • 分离之后的线程是不在受约束和管制,会单独执行,直到执行完毕释放资源,可以看做是一个daemon线程;
    • 分离之后thread对象不再表示任何线程;
    • 分离之后joinable() == false,即使还在执行;
  • join方式,等待启动的线程完成,才会继续往下执行。假如前面的代码使用这种方式,其输出就会0,1,2,3,因为每次都是前一个线程输出完成了才会进行下一个循环,启动下一个新线程。
    • 只有处于活动状态线程才能调用join,可以通过joinable()函数检查;
    • joinable() == true表示当前线程是活动线程,才可以调用join函数;
    • 默认构造函数创建的对象是joinable() == false;
    • join只能被调用一次,之后joinable就会变为false,表示线程执行完毕;
    • 调用 ternimate()的线程必须是 joinable() == false;
    • 如果线程不调用join()函数,即使执行完毕也是一个活动线程,即joinable() == true,依然可以调用join()函数;

向线程传递参数

向线程调用的函数传递参数也是很简单的,只需要在构造thread的实例时,依次传入即可。例如

int Simple_func(int a, int b);
std::thread t(Simple_func,1,2);

需要注意的是,默认的会将传递的参数以拷贝的方式复制到线程空间,即使参数的类型是引用,如果在线程中使用引用来更新对象时,就需要注意了。默认的是将对象拷贝到线程空间,其引用的是拷贝的线程空间的对象,而不是初始希望改变的对象。例如:

int ChangeNum(int &a);
int num=0;
std::thread t(ChangeNum,num);
t.join();

在线程内,将对象的字段a和b设置为新的值,但是在线程调用结束后,这两个字段的值并不会改变。这样由于引用的实际上是局部变量num的一个拷贝。

若想通过线程改变对象值,需调用std::ref,将num的引用传入线程,如:

std::thread t(ChangeNum,std::ref(num));

thread是可移动的(movable)的,但不可复制(copyable)。可以通过move来改变线程的所有权,灵活的决定线程在什么时候join或者detach。

std::thread也可以去包装一个类,前提是该类对()操作符进行了重载,使其相当于拥有了函数的性质。(此处类似于std::bind的绑定)


 

在多线程编程的时候,资源竞争是很常见的问题,因此需要引入互斥锁。c++11中提供了std::mutex,而在C++17开始,标准库提供了shared_mutex类。

对于shared_mutex,可以理解为共享锁,允许多个线程同时对同一资源进行操作。而lock_guard、unique_lock可以理解为独占锁,只允许一个线程对资源进行操作。

在一些只读函数中可以用std::shared_mutex,而在写操作函数中需用std::unique_lock。

std::shared_mutex是c++17中引入的,不支持std::mutex,需用std::shared_mutex声明互斥信号量。

 

参考文章:https://immortalqx.github.io/2021/12/04/cpp-notes-3/

 

标签:std,多线程,join,thread,调用,mutex,线程,unique
From: https://www.cnblogs.com/Explosion556/p/17275743.html

相关文章

  • 多线程队列接收
    packageorg.example.file.mult;//函数值接口@FunctionalInterfacepublicinterfaceFuncationCallback{voidcallback(Stringparam);} 回调接收 packageorg.example.file.mult;importjava.util.ArrayList;publicclassFuncationCallbackImpl{......
  • C#:多线程
    在C#中,多线程是一种非常常见的编程方式,它可以提高程序的并发性和响应性。但是,多线程编程也是一种比较复杂的编程方式,需要开发者具备一定的经验和技能。本文将介绍C#中多......
  • 多线程源码_三菱plc+卡+串口上位机
    多线程源码_三菱plc+卡+串口上位机1,采用C#编程。2,上位机采用RS232串口通信链接plc。3,PLC为三菱。4,研华采集卡,采集压装电压。5,曲线判据自定义。6,每天作业......
  • 【Redis】多线程Redis的N种架构
    【Redis】多线程Redis的N种架构为什么需要多线程的Redis在单点上利用更多的资源--热点资源官方的多线程只看左边部分其实还是单线程的形式,设置io Thread的数量==》......
  • C++标准库中的std::nth_leement
    std中的nth_element默认求的是数组中第n小的元素可以通过参数传入,求第n大的元素示例代码#include<algorithm>#include<iostream>#include<vector>usingna......
  • 多线程 互斥锁与读写锁 概念
    一、多线程lock互斥锁简述多线程环境中,不使用lock锁,会形成竞争条件,导致A线程与B线程数据使用冲突。使用lock锁可以保证当有线程操作某个共享资源时,能使该代码块按照指......
  • 多线程socketserver
    模块:socketservertcp协议:服务端:importsocketserverclassMyRequestHandle(socketserver.BaseRequestHandler):defhandle(self):#print(self.request)#......
  • FastDFS并发问题的排查经历
    附件用的fastdf上传和下载的,本地开发时就没考虑过多文件上传就会有并发的问题,比如多个只上传成功了一个或者上传了但是文档内容缺失了,变成0字节。呵。。都是一次难忘的经......
  • c++11 std::thread 线程实例在退出后管理线程调用join()后再新建线程将可能会产生相同
    [03-2816:52:54.372][info][vthread.cpp:92operator()()]createnewthread,id:4,tid:7f5cbb7fd640,inroduce:testvthread003[03-2816:52:54.372][info][vthread......
  • 【面试专栏】Java创建多线程的五种方式
    1.继承Thread类importlombok.extern.slf4j.Slf4j;importorg.junit.jupiter.api.Test;/***继承Thread类创建多线程单元测试**@authorCL*/@Slf4jpublic......