C++线程学习1,线程创建的多种方式

1, 直接创建一个线程

#include <iostream>
#include <thread>
using namespace std;

void Mythread()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "mythread id = " << this_thread::get_id() << endl;
        //this_thread::sleep_for(10ms);
        this_thread::sleep_for(chrono::seconds(1));
    }
    cout << "mythread end  id = " << this_thread::get_id() << endl;
}

int main()
{
    cout << "Main thread id =  " << this_thread::get_id() << endl;
    thread th(Mythread); //出错
        
    return 0;
}


主线程退出的时候,thread对象被销毁,但是子线程还在运行,所以出错。


2,等待线程退出join()

int main()
{
    cout << "Main thread id =  " << this_thread::get_id() << endl;
    thread th(Mythread);
    th.join();//主线程阻塞,等待子线程退出
    cout << "Main thread STOP" << endl;

    return 0;
}


        在使用thread时。一般需要使用join()等待线程时,不会在创建后立即调用join(),因为这样可能会导致创建线程去等待这个线程执行完成才能继续执行;所以在使用join的时候就需要特别注意使用join的位置和时机。特别创建线程的是主线程的时候,如果子线程需要执行很长时间,那么可能会让主线程处于等待中,那么可能就会导致界面假死的情况(界面编程的时候)。

3,分离子线程detach()

int main()
{
	cout << "Main thread id =  " << this_thread::get_id() << endl;
	thread th(Mythread);					//OK 
	th.detach();//主线程与子线程分离,守护线程(子线程在后台运行)
	cout << "Main thread STOP  " << endl;	
    
	return 0;
}

        detach()的作用是将子线程和主线程的关联分离,分离之后,子线程在后台独立运行,主线程无法拿到子线程的控制权,即使主线程结束子线程也不会结束。

坑:当主线程结束时,不管子线程的逻辑是不是已经执行完,主线程会释放清理与子线程相关的一些变量或者数据资源。因此涉及从其他线程传递到子线程参数或数据的时候,一般使用值传递,而不是用引用和指针。

 4,使用一个控制变量

#include <iostream>
#include <thread>
using namespace std;
bool is_run = false;
void Mythread()
{
	for (int i = 0; i < 5; i++)
	{
		if (!is_run)
			break;
		cout << "mythread id = " << this_thread::get_id() << endl;
		//this_thread::sleep_for(10ms);
		this_thread::sleep_for(chrono::seconds(1));
	}
	cout << "mythread STOP" << endl;
}
int main()
{
	cout << "Main thread id =  " << this_thread::get_id() << endl;
	thread th(Mythread);
	is_run = true;//通知子线程退出
	th.join();//主线程阻塞,等待子线程退出
    cout << "Main thread STOP" << this_thread::get_id() << endl;

	return 0;
}

5,全局函数作为函数入口(参数的传递)

5.1,值传递:

#include <iostream>
#include <thread>
#include <string>
using namespace std;

class Para
{
public:
	Para() { cout << "Para create" << endl; }
	~Para() { cout << "Para drop" << endl; }

public:
	string name;
};

void Mythread(int int_1, string str_2, Para p)
{
	cout << "int_1 = " << int_1 <<"\t" << "str_2 = " << str_2 << endl;
	cout << "name = " << p.name << endl;
}

int main()
{
	Para p;
	p.name = "str_test";
	thread th(Mythread,100,"string",p); //所有参数做复制
	th.join();

	return 0;
}

 chup三次的原因:创建一次+copy两次;main函数中创建类对象的时候一次,创建线程对象的时候,内部有一个值copy,copy一次,进入线程函数中再copy一次。

参数传递的坑:

  1. 传递控空间已经销毁。
  2. 多线程共享访问一个空间。
  3. 传递的指针变量的生命周期小于线程的生命周期。

5.2,指针传递

void MythreadPtr(Para* p)
{
	cout << "MyThreadPtr naem =  " << p->name << endl;
}

int main()
{
	{
		Para p;
		p.name = "MyThreadPtr";
		thread th(MythreadPtr, &p); //所有参数做复制
		th.join();
		getchar();
	}

    return 0;
}

使用指针传递,只是创建、drop了一次。 

  • 现在让主线程和子线程分离,然后让主线程先退出
void MythreadPtr(Para* p)
{
	//为了保证主线程比子线程先退出
	this_thread::sleep_for(10ms);
	cout << "MyThreadPtr naem =  " << p->name << endl;
}

int main()
{
	{
		Para p;
		p.name = "MyThreadPtr";
		thread th(MythreadPtr, &p); //所有参数做复制
		th.detach();
	}
	getchar();

    return 0;
}

发生错误,线程访问的空间p被提前释放,里面的被清理,访问错误。

  • 传递引用
int main()
{
    {
		Para p;
		p.name = "MyThreadRef";
		thread th(MythreadPtr, ref(p)); //ref标识传递为引用
		th.detach();
	}
	getchar();
}

在引用传递的时候,要主动地标识为引用传递ref()。 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值