多线程学习笔记4

6 篇文章 7 订阅
6 篇文章 0 订阅
std::condition_variable
notify_one()
wait()
class A{
public:
   std::unique_lock<std::mutex> my_move(){
   	std::unique_lock<std::mutex> tem(my_mutex1);
   	return tem;
   }
   void inmRQ(){
   	for(int i=1;i<=100000000;i++){
   		cout<<"start"<<endl;
   		std::unique_lock<std::mutex> myguard(my_mutex1);
   		mRQ.push(i);
   		my_cond.notify_one();//我们把wait()的线程唤醒,执行完这行,那么outmRQ()里的wait就会被唤醒(只能唤醒一个线程)
   	}
   }

   void outmRQ(){
   	int command=0;
   	while (true){
   		std::unique_lock<std::mutex> mygurad(my_mutex1);
   		
   		//wait()用来等一个东西
   		//如果第二个参数lambda表达式返回值是flase,那么wait()将解锁互斥量,并堵塞到本行
   		//如果为true , 那么wait()直接返回
   		//堵塞到其他线程调用notify_one()成员函数为止
   		//如果写成my_cond.wait(mygurad)那么就和第二个参数返回flase一样

   		//当其他线程调用了notify_one()将本wait唤醒后
   			//a)如果wait不断尝试获取互斥锁,直到获取成功
   			//b)如果有第二个参数,就执行判断,如果为true就向下执行,如果为flase就又解锁则塞
   			//b)如果没有第二个参数,这直接向下执行				
   		my_cond.wait(mygurad ,[this]{
   			if( !mRQ.empty() )
   				return true;
   			return false;
   		});
   		command=mRQ.front();
   		mRQ.pop();//操作共享数据
   		mygurad.unlock();
   		cout<<command<<endl;
   		//其他操作
   	}
   	
   }
private:
   std::queue<int> mRQ;
   std::mutex my_mutex1;
   std::condition_variable my_cond;//生成一个条件变量对象 
};
notify_all()

尝试把该condition_variable对象的wait线程全都唤醒

单例设计模式

单例 , 在整个项目中 , 有属于某个或者某些特殊的类 , 属于该类的对象 , 我只能创建一个 , 多了创建不了

class A{
private:
	A(){} //私有化构造函数
	static A *mya;//静态成员函数
public:
	static A* GetInstance(){
		if( mya==NULL ){
			mya = new A();
		}
		return mya;
	}
	void test(){
		cout<<"测试"<<endl;
	}
};
A* A::mya = NULL;

int main(){
	A *p_a = A::GetInstance();//创建一个对象 , 返回该类对象指针
	A *p_b = A::GetInstance();
	return 0;
}
单例技巧
class A{
private:
	A(){} //私有化构造函数
	static A *mya;//静态成员函数
public:
	static A* GetInstance(){
		if( mya==NULL ){
			mya = new A();
			static CGhuishou c;
		}
		return mya;
	}
	class CGhuishou{//类中套类 , 用来释放对象
	public:
		~CGhuishou(){
			if( A::mya ){
				delete A::mya;
				A::mya = NULL;
			}
		}
		
	};
	void test(){
		cout<<"test"<<endl;
	}
};
A* A::mya = NULL;

int main(){
	A *p_a = A::GetInstance();//创建一个对象 , 返回该类对象指针
	A *p_b = A::GetInstance();
	p_a->test();
	return 0;
}
单例设计模式共享数据问题

建议在主线程初始化单例对象

当在线程中初始化单例时 , 就要注意数据共享问题

using namespace std;

std::mutex mymutex;
class A{
private:
	A(){} //私有化构造函数
	static A *mya;//静态成员函数
public:
	static A* GetInstance(){//这里可能会出现reorder问题,请自行百度
		if( mya==NULL ){//双重锁定(双重检查)
			mymutex.lock();
			if( mya==NULL ){
				mya = new A();
				static CGhuishou c;
			}
			mymutex.unlock();
		}
		return mya;
	}
	class CGhuishou{//类中套类 , 用来释放对象
	public:
		~CGhuishou(){
			if( A::mya ){
				delete A::mya;
				A::mya = NULL;
			}
		}
		
	};
	void test(){
		cout<<"test"<<endl;
	}
};
A* A::mya = NULL;

void run1(){
	while (true){
		A* ptr=A::GetInstance();
		cout<<"run1"<<endl;
	}
}
void run2(){
	while (true){
		A* ptr=A::GetInstance();
		cout<<"run2"<<endl;
	}
}

int main(){
	std::thread myjob1(ref(run1));
	std::thread myjob2(ref(run2));

	myjob1.join();
	myjob2.join();
	return 0;
}
std::call_one()

第二个参数是一个函数名a( )

功能 : call_one功能是保证函数a()只被调用一次

具备互斥量能力 , 比互斥量消耗少一点

call_one()需要与一个标记结合使用 , 这个标记 std::once_flag (结构体)

call_one()通过这个标记来决定对应的函数a()是否执行 , 调用call_one()标记std::once_flag 以后a()就不会再执行了

std::mutex mymutex;
std::once_flag flag;

class A{
private:
	A(){} //私有化构造函数
	static A *mya;//静态成员函数
public:
	static void GreatInstance(){//只被调用一次
		cout<<"I was called"<<endl;
		mya = new A();
		static CGhuishou c;
	}
	static A* GetInstance(){
		std::call_once(flag,GreatInstance);
		return mya;
	}
	class CGhuishou{//类中套类 , 用来释放对象
	public:
		~CGhuishou(){
			if( A::mya ){
				delete A::mya;
				A::mya = NULL;
			}
		}
		
	};
	void test(){
		cout<<"test"<<endl;
	}
};
A* A::mya = NULL;

void run1(){
	while (true){
		A* ptr=A::GetInstance();
		cout<<"run1"<<endl;
	}
}
void run2(){
	while (true){
		A* ptr=A::GetInstance();
		cout<<"run2"<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值