互斥锁、条件变量实现线程安全

试想一个场景,对一个链表取数据和存入数据,线程安全,可以做到一对一,一对多或者多对多,,先不考虑无锁实现,


对于互斥锁,只需在读和写的时候加锁,就可以做到线程安全,但是有一个问题,假如链表数据为空的时候,常规的做法是循环睡眠检测是否有数据,这样就浪费了cpu时间片,改进措施就是用条件变量

条件变量:条件变量不同于信号量,没有计数概念,就是说如果产生的信号没有条件变量等待,那么该信号就是丢失,不会有累计的概念,条件变量等待信号也没有消耗的说法。同时也解释下pthread_cond_wait原理,和一个锁搭配使用,在使用之前上锁,然后pthread_cond_wait内部里面会解锁,等待一个条件变量信号的发生,当条件变量等待到信号返回时又上锁(这个过程是pthread_cond_wait内部),外面又解锁,这两种行为是一个互斥,一个等待,为了解决一些特殊场景!

前面场景的改进就是如果没有数据,那么就等待有数据,减少cpu的无效占用,,看我代码吧,条件变量不好就在于等待和上锁时要分开,不能写死在一个函数内,看我下面消费和产生数据的线程

class Mycondition_mutex{
public:
	Mycondition_mutex(){
	pthread_cond_init(&m_cond,NULL);
	pthread_mutex_init(&m_mutex,NULL);	
	}
	~Mycondition_mutex()
	{
		pthread_cond_destroy(&m_cond);
		pthread_mutex_destroy(&m_mutex);
	}
	void lock()
	{
		pthread_mutex_lock(&m_mutex);

	}
	void unlock()
	{
		pthread_mutex_unlock(&m_mutex);

	}

	void wait()
	{
		//pthread_mutex_lock(&m_mutex);
		pthread_cond_wait(&m_cond,&m_mutex);
		//pthread_mutex_unlock(&m_mutex);
		
	}

	
	void signal()
	{

	//	pthread_mutex_lock(&m_mutex);
		//pthread_cond_signal(&m_cond);
		pthread_cond_broadcast(&m_cond);
		//pthread_mutex_unlock(&m_mutex);
	}

private:
		pthread_cond_t  m_cond;
		pthread_mutex_t  m_mutex;
};
void* produce(void *p)
{
	list<int>* ilist= (list<int>*)p;
	while(1)
	{
		g_cond.lock();
		if(data==1E+8)
		{
			flag=1;
			cout << "produce" << data << endl;
			g_cond.unlock();
			break;
		}
		
		ilist->push_back(data);
		//cout<<"produce data:"<<data<<endl;
		data++;
		if(wait_flag==1)
		{
			//cout << "sigmal one" << endl;
			g_cond.signal();
			wait_flag=0;	
		}
		g_cond.unlock();
	}	
	return (void*)1;
}
void* consume(void *p)
{
	list<int>* ilist= (list<int>*)p;
	while(1)
	{
		g_cond.lock();
		if(ilist->empty())
		{
			if(flag==1)
			{
				g_cond.unlock();
				break;
			}	
			else
			{
				//g_lock.unlock();
				wait_flag=1;
				g_cond.wait();
				g_cond.unlock();
				continue;
			}
		}
	int len=ilist->size();
	int data=ilist->front();
	ilist->pop_front();
	//if(data==1999999)
	//cout<<"consume data:"<<data<<endl;
	g_cond.unlock();	
	}
	return (void*)1;
}

这个列子是我为了测试多线程下存取数据的效率,还没过渡到无锁实现,如果存数据之前、取数据之后有一系列的操作,多线程才能发挥效率,在我这个场景里面看到的是某一时刻只有一个线程在存取操作。

Mycondition_mutex g_cond;
int flag=0;
int data=0;
int wait_flag=0;
int main()
{
	list<int> ilist;
	pthread_t pro[5],con[5];
	for (int i = 0; i <5; i++)
		pthread_create(&con[i], NULL, consume, (void*)&ilist);
	for (int i = 0; i <5; i++)
		pthread_create(&pro[i],NULL,produce,(void*)&ilist);

	pthread_join(pro[0],0);
	pthread_join(pro[1],0);
	pthread_join(pro[2], 0);
	pthread_join(pro[3], 0);
	pthread_join(pro[4], 0);

	pthread_join(con[0],0);
	pthread_join(con[1],0);
	pthread_join(con[2], 0);
	pthread_join(con[3], 0);
	pthread_join(con[4], 0);
	return 0;
};

下一步进军无锁队列的实现!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值