多线程编程(二) ----- std::thread

c++11封装了有关多线程编程的类库,使用他们会使多线程编程更为轻松简单,这里就总结一下std::thread的简单实用。

使用std::thread之前我们先来了解有关的函数头和其相关的成员方法

相关的头文件有<thread> <future> <mutex> <condition_variable> <atomic> <condition_variable>

相关成员:

thread

//std::thread::id() 比较是否相等

std::thread::hardware_concurrency()这是一个静态成员函数,返回cpu核心数,即能同时并行的数量

std::thread::swap()   交换线程

std::thread::joinnable() 判断是否要等待

std::thread::join()  等待线程结束才能走下一步

std::thread::datach() 切割,使线程成为孤儿线程,主线程死亡不会对其有影响

std::thread::get_id() 得到线程id

std::this_thread::sleep_for() 等待一段时间

std::this_thread::sleep_until() 等待直到某个时间

future(只能移动,不能复制,即默认情况下,在promise和future之间是一对一关系的)

std::future::share()  构造新的shared_future实例,与future的区别是这个能一个关联几个

std::future::wait() 判断有没有返回信息

std::future::wait_for()  判断一段时间内有没有返回信息,没有即算没有返回信息

std::future::wait_until()  判断有没有返回信息,直到某个时间没有即算没有返回

std::future::get() 得到绑定后的线程返回信息

shared_future(这个可以复制,即 std::shared_future 支持了一个一对多的关系,即一个promise多个future。)

std::shared_future::valid() 判断有没有绑定

其他的和future一样

packaged_task(这个和promise的区别是他的形参塞的是函数,promise形参塞得是变量)

std::packaged_task::swap() 交换绑定

std::packaged_task::get_future() 传回信息

std::packaged_task::reset() 更新新的绑定future

std::packaged_task::valid() 判断有没有绑定

std::packaged_task::make_ready_at_thread_exit()

promise(无论是async还是package_task都是将函数返回值作为写入future内容的手段,但很多情况下,设计者希望future只提供读的接口,而暴露出写的接口。这便是promise的目标

std::promise::swap() 交换绑定对象

std::promise::get_future() 返回结果给future

std::promise::set_value() 将一个值赋予promise,用来返回非future

std::promise::set_value_at_thread_exit()  赋值,等到线程结束后才就绪传回

std::promise::set_exception() 将一个异常的值返回给future

std::promise::set_exception_at_thread_exit() 将一个异常的值返回给future,等到线程结束后才就绪传回

mutex

std::mutex::lock() 上锁

std::mutex::try_lock() 检查是否能上锁,能就上

std::mutex::unlock() 解锁

std::recursive_mutex()递归锁

std::timed_mutex()超时锁

std::recursive_timed_mutex() 超时递归锁

std::lock_guard()  智能锁,不用解锁(类似于RAII)

std::unique_lock::swap() 交换锁

std::unique_lock::lock() 上锁(这个也是智能锁,不用解锁,对比lock_guard多了几个构造函数,更加灵活,开销更大)

std::unique_lock::try_lock()

std::unique_lock::unlock()

std::unique_lock::try_lock_for()

std::unique_lock::try_lock_until()

std::unique_lock::owns_lock() 检查自己本身是否有锁

std::unique_lock::mutex() 返回与*this相关的互斥元,如果有的话

std::unique_lock::release()  返回与*this相关的互斥元,如果有的话,并且释放该关联

condition_variable 与unique_lock连用,阻塞知道某个条件为真

std::notify_one()

唤醒当前正在等待的一个线程

std::notify_all()

唤醒当前正在等待的全部线程

std::wait()

一直等待,直到被唤醒(notify_all(),notify_one())

std::wait_for()

比前面多了个时间段

std::wait_until()

比前面那个多了个伪唤醒

condition_variable_any

这里和condition_variable的区别是前者只能和unique_lock()一起使用,any版本可以与任意锁使用

 

使用了原子变量atomic就不需要互斥量了,原子变量即是一个变量值得读取修改回写变成一个不可打断的操作,于是我们就有了原子变量。以下是原子变量的用法:

(附:原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程) 原子操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断 )

 

实例:

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <future>
#include <condition_variable>
//#include <iostream>
std::mutex mux;
std::recursive_mutex rmux;

void ThreadFun1()
{
	{
		mux.lock();//加锁
		std::cout << "创建线程线程" << std::endl;
		mux.unlock();//解锁
	}
}
void Lock_GuartFun2()
{
	//加锁
	std::lock_guard<std::mutex> lock(mux);
	std::cout << "线程Lock_GuartFun" << std::endl;
}
void Unique_Lock2()
{
	std::unique_lock<std::mutex> lock(mux);
	std::cout << "线程Unique_Lock  " ;
	lock.unlock();
	lock.lock();
	std::cout << "刚才我暂时解锁,又上锁了,皮一下很开心" << std::endl;
}
void FuntureFun(std::future<int> &fut)
{
	//获取Promise的值
	auto val = fut.get();
	{
		std::unique_lock<std::mutex> lock(mux);
		//mux.lock(); //多写了这部,直接死锁
		std::cout << "获得promise异步线程的秘密参数i,i = " << val << std::endl;
		
	}
}
void Promise(std::promise<int> &pro)
{
	int i = 10;
	{
		mux.lock();
		std::cout << "给promise赋值,发送给FuntureFun异步线程i的值" << std::endl;
		mux.unlock();
	}
	pro.set_value(i);//赋值
	
	
}
class TF
{
public:
	//重载()
	TF &operator()()
	{
		{
			mux.lock();
			std::cout << "我是一个伪函数,为了测试创建线程里放个类" << std::endl;
			mux.unlock();
		}
		return *this;
	}
};
int RecursiveMutex()
{
	static int i = 0;
	{
		//std::lock_guard<std::mutex> lock(mux); //使用这个锁就会死锁
		std::lock_guard<std::recursive_mutex> lock(rmux);//加递归锁
		std::cout << "我是一个递归函数, 递归了" << i << std::endl;
		++i;
		
	}
	return i < 5 ? RecursiveMutex() : 0;
	

}

int main()
{
	TF f;
	std::future<int> fut;//事实上,保存函数指针,类指针什么的都可以例子:
	std::promise<int> pro;
	fut = pro.get_future();//绑定

	std::thread MyThread1(ThreadFun1);
	std::thread MyThread2([]() {mux.lock();  std::cout << "我是一个lambda" << std::endl; mux.unlock(); });
	std::thread MyThread3(f);
	std::thread MyThread4(Lock_GuartFun2);
	std::thread MyThread5(Unique_Lock2);
	std::thread MyThread6(Promise,std::ref(pro));//传引用要用类似c#的写法
	std::thread MyThread7(FuntureFun, std::ref(fut));//注意,future在收到值之前会一直堵塞,直到收到值。
	std::thread MyThread8(RecursiveMutex);


	MyThread1.join();
	MyThread2.join();
	MyThread3.join();
	MyThread4.join();
	MyThread5.join();
	MyThread6.join();
	MyThread7.join();
	MyThread8.join();//等待线程结束后再执行剩下的
	std::cout << "线程并行数 = " << MyThread1.hardware_concurrency() << std::endl;
	std::cout << "MyThread1线程id = " << MyThread1.get_id() << std::endl;
	system("pause");
    return 0;
}

结果:

 

最后粘上一些总结的很不错的网站:

https://www.jianshu.com/p/c1dfa1d40f53

c++11-----多线程

10分钟带你掌握多线程

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值