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

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


对于互斥锁,只需在读和写的时候加锁,就可以做到线程安全,但是有一个问题,假如链表数据为空的时候,常规的做法是循环睡眠检测是否有数据,这样就浪费了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
    评论
好的,以下是一个使用互斥锁条件变量实现线程间通信的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; // 共享缓冲区 int count = 0; // 缓冲区中元素个数 pthread_mutex_t mutex; // 互斥锁 pthread_cond_t cond; // 条件变量 void *producer(void *arg) { int item = 0; while (1) { pthread_mutex_lock(&mutex); // 加锁 if (count == BUFFER_SIZE) { // 缓冲区已满,等待消费者消费 pthread_cond_wait(&cond, &mutex); } buffer[count++] = item++; // 生产一个物品,放入缓冲区 printf("Producer produces item %d\n", item); pthread_mutex_unlock(&mutex); // 解锁 pthread_cond_signal(&cond); // 唤醒一个等待的消费者 } pthread_exit(NULL); } void *consumer(void *arg) { int item = 0; while (1) { pthread_mutex_lock(&mutex); // 加锁 if (count == 0) { // 缓冲区为空,等待生产者生产 pthread_cond_wait(&cond, &mutex); } item = buffer[--count]; // 消费一个物品,从缓冲区中取出 printf("Consumer consumes item %d\n", item); pthread_mutex_unlock(&mutex); // 解锁 pthread_cond_signal(&cond); // 唤醒一个等待的生产者 } pthread_exit(NULL); } int main() { pthread_t producer_tid, consumer_tid; // 初始化互斥锁条件变量 pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); // 创建生产者和消费者线程 pthread_create(&producer_tid, NULL, producer, NULL); pthread_create(&consumer_tid, NULL, consumer, NULL); // 等待线程结束 pthread_join(producer_tid, NULL); pthread_join(consumer_tid, NULL); // 销毁互斥锁条件变量 pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return 0; } ``` 在上面的示例代码中,我们使用了一个缓冲区来实现生产者和消费者之间的通信。生产者将生产的物品放入缓冲区,消费者从缓冲区中取出物品进行消费。当缓冲区已满时,生产者会等待消费者消费;当缓冲区为空时,消费者会等待生产者生产。在等待的过程中,使用条件变量来进行线程的阻塞和唤醒。当生产者放入一个物品时,会唤醒一个等待的消费者;当消费者取出一个物品时,会唤醒一个等待的生产者。同时,使用互斥锁来保护共享缓冲区的访问,确保线程安全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值