利用条件变量和互斥量循环打印ABC和1-100的错误情况

Posted Jqivin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用条件变量和互斥量循环打印ABC和1-100的错误情况相关的知识,希望对你有一定的参考价值。


循环打印ABC的错误情况

#include<iostream>
#include<mutex>
#include<condition_variable>
#include<queue>
using namespace std;
std::mutex mtx;
std::condition_variable cv;
int flg = 0;

void Print_A()
{
	for (int i = 0; i < 5; i++)
	{
		std::unique_lock<std::mutex> locker(mtx);
		if(flg != 0)
		{
			cv.wait(locker);
		}
		cout << "A";
		flg = 1;
		cv.notify_one();
	}
}
void Print_B()
{
	for (int i = 0; i < 5; i++)
	{
		std::unique_lock<std::mutex> locker(mtx);
		if (flg != 1)
		{
			cv.wait(locker);
		}
		cout << "B";
		flg = 2;
		cv.notify_one();
	}
}
void Print_C()
{
	for (int i = 0; i < 5; i++)
	{
		std::unique_lock<std::mutex> locker(mtx);
		if (flg != 2)
		{
			cv.wait(locker);
		}
		cout << "C ";
		flg = 0;
		cv.notify_one();
	}
}
int main()
{
	thread t1(Print_A);
	thread t2(Print_B);
	thread t3(Print_C);

	t1.join(); t2.join(); t3.join();
	return 0;
}

结果:
在这里插入图片描述
错误一:使用了if导致错误
原因解释:
在这里插入图片描述
错误二:使用了notify_one()函数。
如果只把if改成了while还是有问题,可能会导致死锁。如下面的情况
在这里插入图片描述
原因解释:
这是因为每次如果只唤醒一个线程,可能并不能唤醒我们想要的线程,就比如说,A执行完毕之后,应该唤醒B的,但是我们却唤醒了C,这就导致C也进行判断条件,从而执行cv.wait()进入了阻塞的状态。从而造成了死锁的局面。

最后,把if改成while,notify_one()改成notify_all()就可以了。
在这里插入图片描述

循环打印1-100的错误情况

先来看代码:

//利用三个线程打印1-100的数
int flg = 1;
std::mutex mtx;
std::condition_variable cv;
void fun1()
{
	std::unique_lock<mutex> locker(mtx);
	while (flg <=100)
	{
		
		while (flg % 3 != 1 && flg <=100)
		{
			cv.wait(locker);
			
		}
		cout << flg << " ";
		flg += 1;
		cv.notify_all();
	}
}
void fun2()
{
	std::unique_lock<mutex> locker(mtx);
	while (flg <= 100 )
	{
		
		while (flg % 3 != 2 && flg <= 100)
		{
			cv.wait(locker);
		}
		cout << flg << " ";
		flg += 1;
		cv.notify_all();
	}
}
void fun3()
{
	std::unique_lock<mutex> locker(mtx);
	while (flg <= 100 )
	{
		
		while (flg % 3 != 0 && flg <= 100)
		{
			cv.wait(locker);
		}
		cout << flg << " ";
		flg += 1;
		cv.notify_all();
	}
}
int main()
{
	thread t1(fun1);
	thread t2(fun2);
	thread t3(fun3);

	t1.join(); t2.join(); t3.join();
	return 0;
}

执行结果:
在这里插入图片描述
原因解释:当flg == 100的时候,执行fun1,执行完毕之后(此时fun2,fun3线程处于挂起状态)唤醒所有线程(此时fun2,fun3线程的while条件不满足-flg > 100,所以会执行输出flg);造成多输出两个。
修改:①可以将判断条件改为 <= 98;
②把wait()放在后面,代码如下:

int flg = 1;
std::mutex mtx;
std::condition_variable cv;
void fun1()
{
	std::unique_lock<mutex> locker(mtx);
	while (flg <= 100)
	{
		while (flg % 3 == 1 && flg <= 100)
		{
			cout << flg << " ";
			flg += 1;
			cv.notify_all();
		}
		cv.wait(locker);
	}
	
}
void fun2()
{
	std::unique_lock<mutex> locker(mtx);
	while (flg <= 100)
	{
		while (flg % 3 == 2 && flg <= 100)
		{
			cout << flg << " ";
			flg += 1;
			cv.notify_all();
		}
		cv.wait(locker);
	}
	cv.notify_all(); //为了唤醒最后一个阻塞的线程
}
void fun3()
{
	std::unique_lock<mutex> locker(mtx);
	while (flg <= 100)
	{
		while (flg % 3 == 0 && flg <= 100)
		{
			cout << flg << " ";
			flg += 1;
			cv.notify_all();
		}
		cv.wait(locker);
	}
}

结果:
在这里插入图片描述

以上是关于利用条件变量和互斥量循环打印ABC和1-100的错误情况的主要内容,如果未能解决你的问题,请参考以下文章

交替打印ABC多线程(互斥量+条件变量)

互斥量和条件变量

条件变量

Linux多线程同步之互斥量和条件变量

多线程并发编程

线程资源同步——互斥量和条件变量