C++多线程学习

本文总结了C++中的多线程概念,包括并发、进程和线程的定义,以及多线程并发的实现方式。通过实例演示了线程的启动、结束方法,如join和detach,并展示了如何通过函数、类和lambda表达式定义线程。此外,还讨论了线程传参的注意事项,特别提到了对于简单类型和类对象的传递策略。最后,给出了两个具体的代码示例,展示了线程参数传递的不同情况。
摘要由CSDN通过智能技术生成

C++多线程学习总结1

  1. 并发、进程、线程的基本概念
    并发:一个程序同时执行多个独立的任务,提高效率;
    进程:一个可执行程序运行起来了,就叫创建了一个进程;
    线程:当执行可执行程序时,产生一个进程后,这个主线程(每个进程中 都是唯一的)就随着这个进程默默启动起来了,除了主线程之外,可以通过写代码来创建其他线程,就可以在同一时刻,多干一个不同的事;
    并发的实现
    a.多进程并发
    比如账号服务器一个进程,游戏服务器一个进程。
    服务器进程之间存在通信(同一个电脑上:管道,文件,消息队列,共享内存);(不同电脑上:socket通信技术)
    b.多线程并发
    一个程序中除了主程序中还有其他的线程;

  2. 线程启动,结束的方法
    join:意为汇合,子线程和主线程回合;
    detach:分离,主线程不再与子线程汇合,不再等待子线程;
    joinable:判断是否可以成功使用join()或者detach(),true则表示能调用;

  3. 定义线程的方法
    函数

    void myThread1(int i)
    {
    	cout << "子线程开始" << i << endl;
    }
    thread myThread(myThread1,5);
    myThread.join();
    

    class Ta
    {
    public:
    	void operator()() //不能带参数
    	{
    		cout << "我的线程开始运行" << endl;
    		//-------------
    		//-------------
    		cout << "我的线程运行完毕" << endl;
    	}
    };
    
    //main函数里的:
    	Ta ta;
    	thread myThread(ta);
    	myThread.join();
    

    lambda表达式

    //main函数中
    auto lambdaThread = [] {
    		cout << "我的线程开始执行了" << endl;
    		//-------------
    		//-------------
    		cout << "我的线程开始执行了" << endl;
    	};
    
    	thread myThread(lambdaThread);
    	myThread.join();
    

    用某个类中的某个函数

    class Data_
    {
    public:
        void GetMsg(){}
        void SaveMsh(){}
    };
    //main函数里
        Data_ s;
        //第一个&意思是取址,第二个&意思是引用,相当于std::ref(s)
        //thread oneobj(&Data_::SaveMsh,s)传值也是可以的
        //在其他的构造函数中&obj是不会代表引用的,会被当成取地址
        //调用方式:对象成员函数地址,类实例,[成员函数参数]
    	//第二个参数可以传递对象s,也可以传递引用std::ref(s)或&s
    	//传递s,会调用拷贝构造函数在子线程中生成一个新的对象
    	//传递&,子线程中还是用的原来的对象,所以就不能detach,因为主线程运行完毕会把该对象释放掉
        thread oneobj(&Data_::SaveMsh,&s);
        thread twoobj(&Data_::GetMsg,&s);
        oneobj.join();
        twoobj.join();
    
  4. 线程传参注意事项
    如果传递int这种简单类型,直接使用值传递,不要用引用;
    如果传递类对象,避免使用隐式类型转换,全部都是创建线程这一行就创建出临时对象,然后在函数参数里,用引用来接,否则还会创建出一个对象
    实例

    #include <iostream>
    #include <thread>
    using namespace std;
    
    class A {
    public:
    	mutable int m_i; //m_i即使实在const中也可以被修改
    	A(int i) :m_i(i) {}
    };
    
    void myPrint(const A& pmybuf)
    {
    	pmybuf.m_i = 199;
    	cout << "子线程myPrint的参数地址是" << &pmybuf << "thread = " << std::this_thread::get_id() << endl;
    }
    
    int main()
    {
    	A myObj(10);
    	//myPrint(const A& pmybuf)中引用不能去掉,如果去掉会多创建一个对象
    	//const也不能去掉,去掉会出错
    	//即使是传递的const引用,但在子线程中还是会调用拷贝构造函数构造一个新的对象,
    	//所以在子线程中修改m_i的值不会影响到主线程
    	//如果希望子线程中修改m_i的值影响到主线程,可以用thread myThread(myPrint, std::ref(myObj));
    	//这样const就是真的引用了,myPrint定义中的const就可以去掉了,类A定义中的mutable也可以去掉了
    	thread myThread(myPrint, myObj);
    	myThread.join();
    	//myThread.detach();
    
    	cout << "Hello World!" << endl;
    }
    
    #include <iostream>
    #include <thread>
    #include <memory>
    using namespace std;
    
    void myPrint(unique_ptr<int> ptn)
    {
    	cout << "thread = " << std::this_thread::get_id() << endl;
    }
    
    int main()
    {
    	unique_ptr<int> up(new int(10));
    	//独占式指针只能通过std::move()才可以传递给另一个指针
    	//传递后up就指向空,新的ptn指向原来的内存
    	//所以这时就不能用detach了,因为如果主线程先执行完,ptn指向的对象就被释放了
    	thread myThread(myPrint, std::move(up));
    	myThread.join();
    	//myThread.detach();
    
    	return 0;
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值