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

1, 直接创建一个线程

#include 
#include 
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 
#include 
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 
#include 
#include 
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;
}

C++线程学习1,线程创建的多种方式_第1张图片

 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;
}

C++线程学习1,线程创建的多种方式_第2张图片

使用指针传递,只是创建、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;
}

C++线程学习1,线程创建的多种方式_第3张图片

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

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

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

你可能感兴趣的:(C++,c++,开发语言)