C++并发与多线程学习笔记--参数传递详解
- 传递临时对象
- 陷阱
- 总结
- 临时对象作为线程参数
- 线程id的概念
- 临时对象构造时的抓捕
- 成员函数指针做线程函数
传递临时对象作为线程参数
创建的工作线程不止一个,线程根据编号来确定工作内容。每个线程都需要知道自己的编号。线程中有很多容易犯错的写法
例子1
多线程需要执行的函数:
void my_print(const int &i, char* p_mybuff)
{
cout << i << endl;
cout << p_mybuff << endl;
return ;
}
主函数的写法
int mvar = 1;
int& mvary = mvar;
char mybuf[] = "this is a test!";
thread myobj(my_print, mvar, mybuf);
myobj.join(); cout << "Main Thread!!!" << endl;
解释:注意陷阱!!!引用和指针的变量传参。
引用:表面看起来似乎正确,但是细节上有很多地方需要注意的,如果把join()改成detach(),然后主线程和子线程分别执行,那么可能出现主线程执行完了,但是传递进去的参数(引用形式)的资源已经被释放了,有没有可能出现错误?:
myobj.detach()
在创建thread对象的时候,做了一个复制,把值复制进去了,所以不是一个真引用,实际是值传递,不会出现资源释放的错误。但是反过来想,那么主线程的变量的值并不会改变。
指针:如果传递的参数是指针,第二个参数不安全,如果用detach()执行线程的时候,不推荐用“引用”,指针绝对会有问题!
正确的用法是什么样:不传引用,如果要传字符串的情况。
char* p_mybuff 改成 const string &p_mybuff ,确实不指向于同一块内存,什么时候出现了变量类型的转换?事实上存在主函数执行完了,p_mybuff 都被回收了,系统才用p_mybuff 去转换string
thread myobj(my_print, mvar, string(mybuf));
如果用一个string 去强制类型转换,生成一个临时对象,此时的临时对象会绑定到p_mybuff上。在创建线程的时候,构造临时变量的方法传递参数是可行的,此时也会调用一次构造函数,此时detach也能正确运行。为了防止主线程退出,子线程内存的非法引用。
1) 对传递int,直接用值传递。
2) 如果传递类对象,避免隐式类型转换。全部都在创建线程的时候就构建出临时对象,在函数参数里用引用来接收传递的函数。否则系统还会多构造一次函数,造成不必要的浪费。
3) 主线程中类型转换,那么A(mysecondpar) 这一步由主线程操作
thread myobj(myprint, mvar, A(mysecondpar));
thread myobj(myprint, mvar, mysecondpar);
4) 建议不使用detach,用join
传递临时对象作为线程参数
线程ID:在操作系统的层面需要调度线程,有一个线程ID,以及线程ID的文件描述符,用来管理这个线程的资源分配。在线程之间需要调度,所以也有优先级的概念。每个线程对应一个ID,线程ID可以用C++标准库里面的函数来获取 std::this_thread::get_id()。
传参函数给线程的时候,参数入口都是const,在函数中const不能修改,如果需要修改变量,就在初始化的时候“mutable”。在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,但是在多线程里面也有问题,如果真的要修改值,那么就使用std:ref(),这个ref和在C#里面是类似的,将方法内的变量改变后带出方法外,用std:ref(),真正地把变量传进去。
完整的代码:
#include "pch.h"
#include <iostream>
#include <thread> using namespace std; class person {
public:
int m_age;
person(int a) :m_age(a) {
cout << "person 的构造函数,进程为:" << std::this_thread::get_id()<<endl;
}
person(const person &p) :m_age(p.m_age) {
cout << "person 的复制构造函数 " << std::this_thread::get_id() << endl;
}
~person() {
cout << "person的析构函数 " << std::this_thread::get_id() << endl;
} };
void myprin(const int &num, char *p[]) {
cout << "现在的线程是: " << std::this_thread::get_id() << endl;
cout << "传入的参数是:" << endl;
cout << num << " " << p << endl;
}
void print_class(person p)
{
cout << "现在的线程是: " << std::this_thread::get_id() << endl;
cout << "print class: " << p.m_age << endl;
} int main()
{ std::cout << "主线程: "<< std::this_thread::get_id()<<endl; int num = 1;
//person student(num);
thread obj(print_class, person(10)); }
传递成员函数到线程中
将类的成员函数传递到线程中。
std::thread myobj(&classA::method, para1, para2,..);
myobj.join();
classA::method就是一个函数。
C++并发与多线程学习笔记--参数传递详解的更多相关文章
- C++并发与多线程学习笔记--unique_lock详解
unique_lock 取代lock_quard unique_lock 的第二个参数 std::adopt_lock std::try_to_lock std::defer_lock unique_ ...
- C++并发与多线程学习笔记--atomic
std::atomic std::async std::atomic 一般atomic原子操作,针对++,--,+=,^=是支持的,其他结果可能不支持. 注意 std::atomic<int&g ...
- Angular6 学习笔记——组件详解之组件通讯
angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...
- Angular6 学习笔记——组件详解之模板语法
angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...
- Angular6 学习笔记——路由详解
angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...
- JavaScript学习笔记-实例详解-类(二)
实例详解-类(二) //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...
- JavaScript学习笔记-实例详解-类(一)
实例详解-类(一): //每个javascript函数(除了bind())都自动拥有一个prototype对象// 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性const ...
- Android学习笔记-Dialog详解
1.对话框的使用 1.1AlertDialog的显示 简单对话框以及监听的设置:重点掌握三个按钮(也就是三上单词): PositiveButton(确认按钮);NeutralButton(忽略按钮) ...
- C++并发与多线程学习笔记--基本概念和实现
基本概念 并发 可执行程序.进程.线程 学习心得 并发的实现方法 多进程并发 多线程并发 总结 C++标准库 基本概念 (并发.进程.线程)区分C++初级编程和中高级编程 并发 两个或者更多的任务同时 ...
随机推荐
- Python 2 to Python 3 convert
Python 2 to Python 3 convert 2to3, 自动将 Python 2 代码转为 Python 3 代码 https://docs.python.org/zh-cn/2/lib ...
- clientHeight & offsetHeight & scrollHeight
clientHeight & offsetHeight & scrollHeight scrollWidth/scrollHeight,offsetWidth/offsetHeight ...
- py django 渲染前端打包的视图
前端打包后基本这样 $ ls dist /static index.html 在index.html中的publicPath指向static 1. 创建一个www模块 $ python manage. ...
- The Filesystem Hierarchy Standard of Linux
The Filesystem Hierarchy Standard of Linux linux directory https://zhuanlan.zhihu.com/p/23862856 htt ...
- ng 基础
文档 组件的工作只管用户体验,而不用顾及其它. 它应该提供用于数据绑定的属性和方法,以便作为视图和应用逻辑的中介者 组件应该把诸如从服务器获取数据.验证用户输入或直接往控制台中写日志等工作委托给各种服 ...
- Flutter 真机调试
先把手机开启开发者模式,并打开USB调试功能(每种机型开启方法可能不一样) flutter devices 查看是否连接 flutter run
- 【HTB系列】靶机Access的渗透测试详解
出品|MS08067实验室(www.ms08067.com) 本文作者:大方子(Ms08067实验室核心成员) Hack The Box是一个CTF挑战靶机平台,在线渗透测试平台.它能帮助你提升渗透测 ...
- 《进击吧!Blazor!》第一章 5.组件开发
<进击吧!Blazor!>是本人与张善友老师合作的Blazor零基础入门系列视频,此系列能让一个从未接触过Blazor的程序员掌握开发Blazor应用的能力. 视频地址:https://s ...
- 用Vue3构建企业级前端应用,TS能让你更轻松点
摘要:Vue 3已经发布有一段时间了,到底有哪些新特性值得关注,如何用它构建企业级前端项目,怎样快速上手Vue 3?本篇文章将对此进行详细讲解. 前言 工欲善其事,必先利其器 --<论语> ...
- 错误信息:...\output\project.axf: error: l6218e: undefined symbol usart1_confing (referred from main.o).
说明:此文档知识用来记录,顺便给大家作为参考,如有错误的地方请大家多多指正,在下内心定会感激不尽. 前言:关于这个问题,我曾花了一个下午在网上寻找,网上的说法五花八门,我办法试尽,但遍寻无果.由此我认 ...