C++_Windows系统下如何创建多线程

发布于:2024-04-03 ⋅ 阅读:(79) ⋅ 点赞:(0)


前言

对于多线程,之前几章内容已经详细讲解了Linux环境下如何创建多线程,本章内容主要讲解Windows环境下多线程的创建和使用,对于多线程的基本概念在这里不做过多的补充。


一、thread

#include< thread >

由于在windows中我们不再能使用pthread库,因为pthread是unix系统的原生系统库,所以,我们需要包 #include< thread > 头文件。

该头文件包含了thread类及其相关函数,并且不再像pthread库一样通过调用系统接口函数来创建多线程,而是通过对象来帮我们创建多线程。

以我们之前写的抢票多线程程序示例
示例代码如下

#include<iostream>
#include<thread>
#include<string>
#include<mutex>
#include<condition_variable>

int tickets = 10000;
std::mutex mutex;
void task(std::string name)
{

	while (1)
	{
		mutex.lock();
		if (tickets)
		{
			tickets--;
			std::cout << name << " : " << tickets << std::endl;
		}
 
		mutex.unlock();
	}
	
}
int main()
{

	std::thread t1(task,"thread 1");
	std::thread t2(task, "thread 2");
	std::thread t3(task, "thread 3");
	t1.join();
	t2.join();
	t3.join();
	return 0;
}

在这里插入图片描述
这里的thread对象的初始化可以是无参构造,而另一种构造的参数fn是你的新线程要运行的函数,args则是参数包。

mutex

提供了lock_guard和unique_lock来对我们的互斥锁进行了一种保护。
lock_guard的原理则是

#include<iostream>
#include<thread>
#include<string>
#include<mutex>
#include<condition_variable>

class lockGuard
{
public:
	lockGuard(std::mutex& mutex)
		:_mutex(mutex)
	{
		_mutex.lock();
	}

	~lockGuard()
	{
		_mutex.unlock();
	}
private:
	std::mutex& _mutex;
};

int tickets = 10000;
std::mutex mutex;

void task(std::string name)
{
	while (1)
	{
		lockGuard lock(mutex);
		if (tickets)
		{
			tickets--;
			std::cout << name << " : " << tickets << std::endl;
		}
		else
		{
			break;
		}
	}
}
int main()
{

	std::thread t1(task,"thread 1");
	std::thread t2(task, "thread 2");
	std::thread t3(task, "thread 3");
	t1.join();
	t2.join();
	t3.join();
	return 0;
}

而unique_lock和lock_guard不同之处就在于unique_lock可以根据工作任务需求临时解锁再上锁。

二、奇偶双线程打印

上面的代码我们可以知道还缺少了条件变量来控制我们的多线程,我们再来看另外一种示例代码,然后大家如果有时间自行再对上面的抢票程序进行优化。

#include<condition_variable>

在这里插入图片描述
条件变量的使用也变成了通过调用对象的成员函数来使用。

对象名.wait() 类似于使用pthread_cond_wait(mutex) .
对象名.notify_one() 类似于使用pthread_cond_signal(mutex).
对象名.notify_all() 类似于使用pthread_cond_broadcast(mutex).

其中wait()需要unique_lock类型才能使用。
在这里插入图片描述

示例代码如下

#include<iostream>
#include<thread>
#include<string>
#include<mutex>
#include<condition_variable>
int main()
{
	//奇偶双线程
	std::thread threads[2];

	int n = 1000;
	std::mutex mtx;
	std::condition_variable cv;

	threads[0] = std::thread([&]() {
		while (1)
		{
			//std::lock_guard<std::mutex>lock(mtx); //RAII
			std::unique_lock<std::mutex>lock(mtx);
			if (n % 2 != 0) //偶数则线程1打印
			{
				cv.wait(lock); //奇数则阻塞
			}
			if (n > -1)
			{
				std::cout << "thread 1" << " : " << n << std::endl;
				n--;
				cv.notify_one();
			}
			else
			{
				cv.notify_one();
				break;
			}
		}
		} );

	threads[1] = std::thread([&]() {
		while (1)
		{
			//std::lock_guard<std::mutex>lock(mtx);
			std::unique_lock<std::mutex>lock(mtx);
			if (n % 2 == 0) //奇数则线程2打印
			{
				cv.wait(lock); //偶数则阻塞
			}
			if (n > -1)
			{
				std::cout << "thread 2" << " : " << n << std::endl;
				n--;
				cv.notify_one();
			}
			else
			{
				cv.notify_one();
				break;
			}
		}
		});


	threads[0].join();
	threads[1].join();
	return 0;
}

在上面的示例代码需要注意的是 我们使用了thread的移动拷贝构造和lambda表达式来初始化。
在这里插入图片描述