C++面向对象多线程编程简介

多线程编程引发的问题:死锁、无限延迟、数据竞争等。并发编程包括多任务(多进程)和多线程。

使用多线程编程时需包含头文件,具体测试程序代码如下:

#include 
#include 
using namespace std;
void function_1(){
	cout<<"Hello world!"<
C++面向对象多线程编程简介_第1张图片

以下为数据竞争和互斥对象的说明实例,使用互斥锁需要头文件,最基础的方法就是使用lock和unlock方法,使中间部分为临界区,不过这种方法存在临界区部分抛出异常的问题,因此提出了lock_guard  guard(mu);的方法,能够在临界区部分抛出异常后解锁,不过由于cout函数是公开的所以依然不能保证打印准确,所以建立一个写文件类保护输出对象,同时成员变量mutex对一些函数的访问可以实现互斥。

#include 
#include 
#include 
#include 
using namespace std;
mutex mu;
void shared_print(string str,int i){
	lock_guard guard(mu);//尽量使用这种保护的互斥锁,因为能够避免加锁后cout抛出异常的情况,lock_guard能够在抛出异常时自动解锁 
	//mu.lock();//使用mutex互斥锁 ,不过这种直接使用lock和unlock的方式不安全,若出现异常就完了 
	cout< guard(m_mu);
			fout<-10;i--)
	shared_print("main",i);
	t1.join();//确保t1进程进行完毕
	lofFile lof;
	thread t2(fun2,ref(lof));	
	for(int i=0;i>-10;i--)
	lof.shared_print("main",i);
	t2.join();		
}
C++面向对象多线程编程简介_第2张图片

C++面向对象多线程编程简介_第3张图片

死锁问题:下例说明了出现死锁的情况,当临界区要求使用2个及以上的互斥锁时,若加锁的顺序不一致,可能导致死锁。因此为避免死锁程序猿要保证加锁的顺序一致,避免发生死锁,也可以使用C++库函数lock函数按照顺序预先加锁,再使用lock_guard智能解锁。

#include 
#include 
#include 
#include 
using namespace std; 
class lofFile{
	public:
		lofFile(){
			fout.open("log.txt");			
		}
		void shared_print(string str,int i){
			lock(m_mu,m_mu2);//当一些临界区需要2个及以上的互斥锁时,要保证这些不同临界区的互斥锁的加锁顺序要一致,否则可能导致死锁 ,
			//为解决这一问题使用lock()函数提前说明加锁顺序,则lock_guard参数adopt_lock说明已经加锁,只需只能解锁即可 
			lock_guard guard(m_mu,adopt_lock);
			lock_guard guard2(m_mu2,adopt_lock);
			cout< guard(m_mu2,adopt_lock);			
			lock_guard guard2(m_mu,adopt_lock);					
			cout<-10;i--)
	lof.shared_print("main",i);
	t2.join();		
}
导致死锁的情况:程序一直被挂起。。。

C++面向对象多线程编程简介_第4张图片
以下为unique_lock和once_flag的使用实例说明,不过unique_lock相对于lock_guard开销更大。

#include 
#include 
#include 
#include 
using namespace std; 
class lofFile{
	public:
		lofFile(){
			//fout.open("log.txt");			
		}
		void shared_print(string str,int i){
			call_once(m_flag,[&](){fout.open("log.txt");});//使用once_flag可以只调用依次打开文件函数,从而节省开销 
			unique_lock locker(m_mu);//unique_lock相对于lock_guard具有更好的弹性,从而 能够给确定的代码段加锁
			//同时,其对象传递时交出所有权,使用defer_lock参数后,就可以使用lock和unlock实现弹性加锁 
			fout< locker2(m_mu,defer_lock);
			//.......
			locker2.lock();
			//.......
			locker2.unlock();
			//.......
		}
	
	private:
		mutex m_mu;		
		once_flag m_flag;
		ofstream fout;			
};
void fun2(lofFile& lof){
	for(int i=0;i<10;i++)
	lof.shared_print("fun2",i);
}
int main(){	
	lofFile lof;
	thread t2(fun2,ref(lof));	
	for(int i=0;i>-10;i--)
	lof.shared_print("main",i);
	t2.join();		
}


你可能感兴趣的:(C++面向对象多线程编程简介)