c++11线程库

优点:能够跨平台

线程创建

1.范例演示线程的开始运行和结束

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

void myprint()
{
	cout << "子线程...." << endl;
}

int main()
{
	thread t(myprint);
	if(t.joinable())//判断是否能够使用join或者detach 
	{
		//t.join();阻塞等待
		t.detach();//线程分离,与join选择一个使用
	}
	cout << "main..." << endl;
	return 0;
}

2.其他创建线程的手法

//仿函数
#include <iostream>
#include <thread>
using namespace std;
class T
{
public:
	void operator()()
	{
		cout << "子线程...." << endl;
	}
};
int main()
{
	T t;//对象在主线程结束之后会不会出现问题?
	//不会出现问题,t这个对象虽然不在了,但是thread这个类调用的是拷贝构造函数,是复制过去的,所以不会出问题
	thread th(t);
	th.detach();
	cout << "主线程..." << endl;
	return 0;
}
//lambda
int main()
{
	auto th = []{
		cout << "子线程" << endl;
	}
	thread t(th);
	t.join();
	cout << "主线程" << endl;
}

线程传参

传递临时对象作为线程参数

void myprint(const int &i,const string& s)//不用引用要调用三次对象,浪费严重
{
	cout << i << endl;//这里的i不是一个真引用,而是一个假引用,它还是复制过来的,值传递
	cout << s.c_str() << endl;//这里是将str转换为string的引用,也是开辟了一个新空间,但是有一个问题,就是万一转换之前主线程就已经结束了,就会出问题。
}
int main()
{
	int a = 10;
	int &ca = a;
	char str[] = "test";
	thread t(myprint,ca,str);//可能出问题的写法,此时str的对象是在子线程中构造的
	thread t(myprint,ca,string(str));//一定不会出问题,一定会在主线程结束之前构造出来,此时str的对象会先在主线程中构造出来
	t.detach();
	return 0;
}
//thread t(myprint,std::ref(ca),str);	这个就是传引用,但是要注意一定要在子线程结束之后再结束主线程。
//这么记 标准库中的reference
class T
{
public:
	void threadFun()
	{
	}
}
int main()
{
	T a;
	thread t(&T::threadfun,a);//类函数作为线程函数,先传类的函数的地址,再传一个具体的对象,后面有蚕食继续传参数
	return 0;
}

创建和等待多个线程

void myprint(int i)
{
	cout << "子线程" << i << endl;
}
int main()
{
	vector<thread> threads;
	for(int i = 0; i < 10; i++)
		threads.push_back(thread(myprint,i));
	for (auto it = v.begin(); it != v.end(); it++)
		it->join();
	return 0;
}

数据共享问题分析

1.只读的数据
是安全稳定的,不需要什么特别的处理手段。
2.有读有写
读时不写,写时不读。
几个出口就有几个unlock

std::lock_guard<mutex> g_mutex(my_mutex);
//构造里面lock,析构里面unlock,和智能指针有着异曲同工之妙,但有一个缺点,就是不能随性所欲的调用unlock

至少两个互斥量才会产生死锁。
保证两个互斥量加锁的顺序相同(同时先锁一,再锁二)。

std::lock()//函数模板,一次锁住两个或者两个以上的互斥量
//如果互斥量中有一个没锁住,就会在那里等着,等所有互斥量都锁住了,才往下走,如果只锁住了一把锁,就会立即解开。(处理多个互斥量出场)
std::lock(mutex1,mutex2);
//mutex1.unlock();
//mutex2.unlock();
lock_guard<std::mutex> guard1(mutex1,std::adopt_lock);//这样写也是自动解锁
lock_guard<std::mutex> guard2(mutex2,std::adopt_lock);//只是将lock的功能取消了

unique_lock

//较lock_guard灵活,常规使用方式一样
std::aodpt_lock;//用于第二个参数,表示互斥量已经被提前lock了,unique和guard都可以使用


std::try_to_lock;//尝试用mutex的lock()去锁定mutex,但如果没有锁定成功,我也会立即返回,并不会阻塞在那里。所以要使用这个api不能提前锁住。
std::unique_lock<mutex> ulock(my_mutex,std::try_to_lock);
if(ulock.owns.lock())//拿到了锁
else{
	没拿到锁也能干点别的事情
}


std::defer_lock;//与try_to_lock的使用条件一样
//意思是初始化一个没有加锁的的mutex


//成员函数
std::unique_lock<mutex> ulock(my_mutex,std::defer_lock);
ulock.lock();//加锁,不用自己解锁
ulock.unlock();
if(ulock.try_lock())
else {没拿到锁干的事情}
std::mutex *p = ulock.release();//将和unique绑定的mutex分开,让两个之间不再有关系,返回mutex的指针,并且如果mutex在加锁状态,你有责任将它解锁
p->unlock();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值