C++多线程介绍

线程控制块

线程的实体包括程序、数据和线程控制块TCB,TCB包括:

  • 线程状态
  • 当线程不运行时,被保存的线程资源
  • 一组执行堆栈
  • 存放每个线程的局部变量主存区
  • 访问同一进城中的主存和其他资源

上下文切换

image-20211203110018291

image-20211203110138927

image-20211203110212818

常用API

C语言

头文件#include<Windows.h>

CreateThread

image-20211203111327227

image-20211203111339044

image-20211203111547137

image-20211203111645291

image-20211203111741361

#include <Windows.h>
#include <iostream>
using namespace std;
//windows标准调用约定_stdcall
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);

int main()
{
	DWORD threadId = 0;
	HANDLE hThread= CreateThread(NULL, 0, ThreadFun, (void*)"add", 0, &threadId);
	if (NULL == hThread)
	{
		cout << "线程创建失败" << GetLastError() << endl;
	}
	std::cout << "线程句柄:" << hThread << endl;
	cout << "线程的ID:" << threadId << threadId << endl;

}

DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
	char*str = (char*)lpThreadParameter;
	cout << "启动新线程" <<str<< endl;
	return 0;
}
GetCurrentThreadId

DWORD WINAPI GetCurrentThreadId();//得到当前线程ID

CloseHandle

image-20211203120926659

SuspendThread

image-20211203121142671

ResumeThread

在这里插入图片描述

Sleep

在这里插入图片描述

#include <Windows.h>
#include <iostream>
using namespace std;
//windows标准调用约定_stdcall
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);

int main()
{
	DWORD threadId = 0;
	HANDLE hThread= CreateThread(NULL, 0, ThreadFun, (void*)"add", 0, &threadId);
	if (NULL == hThread)
	{
		cout << "线程创建失败" << GetLastError() << endl;
	}
	cout << "线程句柄:" << hThread << endl;
	cout << "子线程的ID:" << threadId  << endl;
	cout << "主线程ID:" << GetCurrentThreadId() << endl;
	//CloseHandle(hThread);//关闭该句柄,表示以后不再引用该句柄
	getchar();
	SuspendThread(hThread);//挂起线程
	getchar();
	ResumeThread(hThread);//恢复句柄
	getchar();
}

DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
	char*str = (char*)lpThreadParameter;
	while (true)
	{
		cout << "线程处理函数" << str << endl;
		cout << "子线程ID:" << GetCurrentThreadId() << endl;
		Sleep(1000);
	}
	
	return 0;
}
WaitForSingleObject

image-20211203162038286

image-20211203162145357

未通知状态:线程的句柄所关联的线程还未结束

#include <Windows.h>
#include <iostream>
using namespace std;
//windows标准调用约定_stdcall
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);

int main()
{
	cout << "主线程开始" << endl;
	HANDLE hThread = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
	WaitForSingleObject(hThread, INFINITE);
	cout << "主线程结尾!" << endl;
	getchar();
}

DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
	int n = 6;
	while (n-->0)
	{
		cout << "子线程hello" << endl;
		Sleep(1000);
	}
	return 0;
}
ExitThread

image-20211203164835968

image-20211203165001924

TerminateThread

image-20211203165331764

image-20211203165431711

GetExitCodeThread

image-20211203165709657

image-20211203165737417

#include <Windows.h>
#include <iostream>
using namespace std;
//windows标准调用约定_stdcall
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);

int main()
{
	cout << "主线程开始" << endl;
	HANDLE hThread = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
	DWORD code;
	GetExitCodeThread(hThread, &code);
	if (code==STILL_ACTIVE)
	{
		cout << "子线程没有退出" << endl;
	}
	WaitForSingleObject(hThread, INFINITE);//等待子线程退出
	GetExitCodeThread(hThread, &code);
	cout << "子线程退出嘛:"<<code << endl;
	cout << "主线程结尾!" << endl;
	getchar();
}

DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
	int n = 6;
	while (n-->0)
	{
		cout << "子线程hello" << endl;
		Sleep(1000);
		if (3 == n)
		{
			ExitThread(1);
		}
	}
	return 0;
}
WaitForMultipleObjects

image-20211204145716663

image-20211204145752218

image-20211204145830916

#include <Windows.h>
#include <iostream>
using namespace std;
//windows标准调用约定_stdcall
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);

int main()
{
	cout << "主线程开始" << endl;
	HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun, (LPVOID)"a", 0, NULL);
	HANDLE hThread2 = CreateThread(NULL, 0, ThreadFun, (LPVOID)"b", 0, NULL);
	HANDLE hThread3 = CreateThread(NULL, 0, ThreadFun, (LPVOID)"c", 0, NULL);
	HANDLE handlesArr[] = { hThread1,hThread2,hThread3 };
	//等待所有线程结束
	DWORD ret = WaitForMultipleObjects(3, handlesArr, true, INFINITE);
    //任一线程结束就返回数组的索引
	DWORD ret = WaitForMultipleObjects(3, handlesArr, false, INFINITE);
	cout << ret << endl;
	cout << "主线程结尾!" << endl;
	getchar();
}

DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
	char* p = (char*)lpThreadParameter;
	if (strcmp(p,"a"))
	{
		Sleep(1000);
	}
	if (strcmp(p, "b"))
	{
		Sleep(2000);
	}
	if (strcmp(p, "c"))
	{
		Sleep(3000);
	}
	cout << p << endl;
	return 0;
}

C++ 语言

image-20211204151901567

image-20211204151911558

image-20211204152045027

#include <process.h>

_beginthread

image-20211204152228506

image-20211204152302834

image-20211204152353891

_endthread

image-20211204152521189

image-20211204153442223

#include <process.h>
#include <iostream>
#include <Windows.h>
using namespace std;
void ThreadFun(void* param);
int main()
{
	cout << "主线程开始" << endl;
	HANDLE hThread=(HANDLE)_beginthread(ThreadFun, 0, (void*)"hello");
	WaitForSingleObject(hThread, INFINITE);
	cout << "主线程结束" << endl;
}
void ThreadFun(void* param)
{
	int n = 0;
	while (++n<=6)
	{
		if (n == 3)
		{
			_endthread();//结束_beginthread创建的线程,不要用ExitThread
		}
		Sleep(500);
		cout << "第" << n << "次" << (char*)param <<endl;
	}
	cout << "子线程结束" << endl;
}

多线程的同步和互斥

异步:各跑各的

同步:接力赛,接棒才可继续

互斥:独木桥,每次只能通过一个人

image-20211204161426625

image-20211204161513678

临界区

image-20211204161701350

类似于电话亭,只能每次进去一个人

image-20211204161759122

image-20211204161902857

image-20211204161917790

image-20211204161952688

image-20211204162006034

image-20211204162156462

#include <process.h>
#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;
void SellThread1(void* param);
int tickets = 100;

//1临界区结构
CRITICAL_SECTION Section;
int main()
{
	cout << "开始卖票" << endl;
	//2初始化临界区
	InitializeCriticalSection(&Section);
	//创建两个售票窗口
	uintptr_t t1 = _beginthread(SellThread1, 0, (void*)"售票1");
	uintptr_t t2= _beginthread(SellThread1, 0, (void*)"售票2");
	
	HANDLE hArr[] = { (HANDLE)t1,(HANDLE)t2 };
	WaitForMultipleObjects(2, hArr, true, INFINITE);
	//5删除临界区
	DeleteCriticalSection(&Section);
	cout << "开始结束" << endl;
}
void SellThread1(void* param)
{
	
	while (tickets>0)
	{

		//3进入临界区,防止其他函数访问 
		//或者使用TryEnterCriticalSection(&Section)这样不会阻塞线程
		EnterCriticalSection(&Section);
		if (tickets>0)//防止最后卖第0张票的情况
		{
			Sleep(100);
			cout << (char*)param << "卖出第" << tickets-- << "张票" << endl;
		}
		//4离开临界区
		LeaveCriticalSection(&Section);
	}
	
}

线程死锁

image-20211204164801915

image-20211204164853692

image-20211204165545405

信号量

image-20211204171108196

image-20211204171204525

image-20211204171515036

image-20211204171700333

#include <Windows.h>
#include <iostream>
#include <process.h>
#include <string>
using namespace std;
DWORD WINAPI ThreadFun(LPVOID param);
struct Car
{
	string name;
	DWORD time;
};
HANDLE hSemaphore = INVALID_HANDLE_VALUE;
int main()
{
	//只有三个停车位资源
	hSemaphore = CreateSemaphore(NULL, 3, 3, L"停车位");
	HANDLE hArr[5] = { INVALID_HANDLE_VALUE };
	for (size_t i = 0; i < 5; i++)
	{
		Car* pCar = new Car;
		pCar->name = 'A' + i;
		cout << "车辆" << pCar->name << endl;
		pCar->time = 3 + i * 2;
		hArr[i] = CreateThread(NULL, 0, ThreadFun, (LPVOID)pCar, 0, NULL);
	}
	WaitForMultipleObjects(5, hArr, true, INFINITE);
}
DWORD WINAPI ThreadFun(LPVOID param)
{
	//如果停车位资源没有满,就放行
	 WaitForSingleObject(hSemaphore, INFINITE);

	 Car* pCar = (Car*)param;
	 cout << pCar->name << "进入停车场" << "   停车" << pCar->time << "秒" << endl;
	 Sleep(pCar->time);
	 cout << pCar->name << "离开停车场" << endl;
	 //释放一个停车位,信号量+1
	 ReleaseSemaphore(hSemaphore, 1, NULL);
	 return 0;
}

image-20211204175016627

image-20211204175116353

互斥量

image-20211204184648504

image-20211204184801366

image-20211204184926933

image-20211204185212257

#include <process.h>
#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;
void SellThread1(void* param);
int tickets = 100;
HANDLE mutex = INVALID_HANDLE_VALUE;

int main()
{
	//1创建互斥体,此时是有信号状态,第二个参数表示主线程是否要拥有该互斥量
	mutex = CreateMutex(NULL, FALSE, L"售票互斥体");
	cout << "开始卖票" << endl;

	//创建两个售票窗口
	uintptr_t t1 = _beginthread(SellThread1, 0, (void*)"售票1");
	uintptr_t t2 = _beginthread(SellThread1, 0, (void*)"售票2");

	HANDLE hArr[] = { (HANDLE)t1,(HANDLE)t2 };
	WaitForMultipleObjects(2, hArr, true, INFINITE);

	cout << "开始结束" << endl;
}
void SellThread1(void* param)
{

	while (tickets > 0)
	{
		//2如果这个互斥体为有信号状态(没有现成拥有它),则获取它后继续执行
		WaitForSingleObject(mutex, NULL);
		if (tickets > 0)//防止最后卖第0张票的情况
		{
			Sleep(100);
			cout << (char*)param << "卖出第" << tickets-- << "张票" << endl;
		}
		//3释放互斥体
		ReleaseMutex(mutex);
	}

}

事件

image-20211204191145588

image-20211204191239084

image-20211204191325695

image-20211204191456564

image-20211204191559018

image-20211204191619208

#include <process.h>
#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;
void SellThread1(void* param);
int tickets = 100;
HANDLE hEvent = INVALID_HANDLE_VALUE;

int main()
{
	//1创建事件对象,此时为自动有信号
	hEvent = CreateEvent(NULL, FALSE, TRUE, L"事件对象");
	cout << "开始卖票" << endl;

	//创建两个售票窗口
	uintptr_t t1 = _beginthread(SellThread1, 0, (void*)"售票1");
	uintptr_t t2 = _beginthread(SellThread1, 0, (void*)"售票2");

	HANDLE hArr[] = { (HANDLE)t1,(HANDLE)t2 };
	WaitForMultipleObjects(2, hArr, true, INFINITE);

	cout << "开始结束" << endl;
}
void SellThread1(void* param)
{

	while (tickets > 0)
	{
		//2如果这个事件为有信号状态(没有现成拥有它),则获取它后继续执行
		//因为是自动的,调用了以下函数对象后,则自动重置为无信号
		WaitForSingleObject(hEvent, INFINITE);
		if (tickets > 0)//防止最后卖第0张票的情况
		{
			Sleep(100);
			cout << (char*)param << "卖出第" << tickets-- << "张票" << endl;
		}
		//3让事件对象变为有信号状态
		SetEvent(hEvent);
	}
}

互斥量和事件都可以像信号量一样实现程序只能打开一例

PV操作

image-20211204194818704

image-20211204195402605

image-20211204195441447

image-20211204195539831

image-20211204195919493

#include <iostream>
#include <process.h>
#include <windows.h>
#include <queue>
using namespace std;
//仓库
queue<int> store;
int StoreSize = 3;//仓库可放三个货物
int ID = 1;//货物ID
//需要两个event来通知
HANDLE hEvent1 = INVALID_HANDLE_VALUE;//仓库为空的时候,通知生产者开始生产
HANDLE hEvent2 = INVALID_HANDLE_VALUE;//有货物时通知消费者取货物
void ProducerThread(LPVOID param);//生产者线程
void ConsumerThread(LPVOID param);//消费者线程

int main()
{
	hEvent1 = CreateEvent(NULL, TRUE, TRUE, L"事件1");
	hEvent2 = CreateEvent(NULL, TRUE, FALSE, L"事件2");//一开始仓库为空
	
	uintptr_t t1 = _beginthread(ProducerThread, 0, NULL);
	uintptr_t t2= _beginthread(ConsumerThread, 0, NULL);
	//无线等待两个线程运行结束
	HANDLE hArr[] = { (HANDLE)t1,(HANDLE)t1 };
	WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
	CloseHandle(hEvent1);
	CloseHandle(hEvent2);
	getchar();
}
void ProducerThread(LPVOID param)
{
	//不断生产,直到仓库已满
	while (TRUE)
	{
		WaitForSingleObject(hEvent1, INFINITE);
		if (store.size()<StoreSize)//有空位
		{
			int id = ID++;
			cout << "生产产品" << id << endl;
			store.push(id);
			Sleep(100);
		}
		else
		{
			ResetEvent(hEvent1);//事件设置为无信号
			cout << "仓库已满" << endl;
		}
		if (store.size() > 0)//仓库有货物
		{
			SetEvent(hEvent2);
		}
	}
}
void ConsumerThread(LPVOID param)
{
	while (true)
	{
		//看是否可以去货物
		WaitForSingleObject(hEvent2, INFINITE);
		if (store.size() > 0)
		{
			int id = store.front();
			store.pop();
			Sleep(200);
			cout << "---------------取货物" << id << endl;
		}
		else
		{
			ResetEvent(hEvent2);
		}
		if (store.size() < 3)
		{
			cout << "####仓库有位置,可生产"<< endl;
			SetEvent(hEvent1);//通知生产者继续生产货物
		}
	}
	
}

线程总结

信号量、互斥、事件都是内核对象,所有都可以使用WaitForSingleObject和CloseHandle

image-20211204204152876


本地存储TLS

image-20211206092821447

image-20211206092955255

image-20211206093022866

#include <windows.h>
#include <iostream>
#include <process.h>

//声明为静态TLS(线程本体存储变量)
_declspec(thread) int N = 0;//每个线程中的值互不影响,每个线程中都有自己的N的拷贝
DWORD WINAPI ThreadFun1(LPVOID param);
DWORD WINAPI ThreadFun2(LPVOID param);
int main()
{
	HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, NULL);
	HANDLE hThread2 = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL);

	HANDLE hArr[] = { hThread1,hThread2 };
	WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
	return 0;
}
DWORD WINAPI ThreadFun1(LPVOID param)
{
	while (true)
	{
		std::cout << "线程1:" << ++N << std::endl;
	}
}
DWORD WINAPI ThreadFun2(LPVOID param)
{
	while (true)
	{
		std::cout << "线程2:" << N << std::endl;//线程2中的N永远为0
	}
}

image-20211206094546705

image-20211206094625546

image-20211206094703230

image-20211206094737820

image-20211206094802016

//三个线程互不影响,自己打印自己的值
#include <windows.h>
#include <iostream>
#include <process.h>

DWORD WINAPI ThreadFun1(LPVOID param);
DWORD WINAPI ThreadFun2(LPVOID param);
DWORD tlsIndex = 0;//动态TLS的索引
int main()
{
	tlsIndex = TlsAlloc();
	if (tlsIndex == TLS_OUT_OF_INDEXES)
	{
		std::cout << "分配TLS索引失败" << std::endl;
		return 0;
	}
	//在主线程中设置一个值
	TlsSetValue(tlsIndex, (LPVOID)"cpp");
	char* p = (char*)TlsGetValue(tlsIndex);
	std::cout << "主线程打印:" <<p<< std::endl;
	HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, NULL);
	HANDLE hThread2 = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL);

	HANDLE hArr[] = { hThread1,hThread2 };
	WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
	TlsFree(tlsIndex);//释放位置
	return 0;
}
DWORD WINAPI ThreadFun1(LPVOID param)
{
	TlsSetValue(tlsIndex, (LPVOID)"hello");
	while (true)
	{
		char* p = (char*)TlsGetValue(tlsIndex);
		//每个线程同一个索引位置的值只属于自己,和其他线程没有关系
		std::cout << "线程1:" << p << std::endl;
	}
}
DWORD WINAPI ThreadFun2(LPVOID param)
{
	TlsSetValue(tlsIndex, (LPVOID)"word");
	while (true)
	{
		char* p = (char*)TlsGetValue(tlsIndex);
		//每个线程同一个索引位置的值只属于自己,和其他线程没有关系
		std::cout << "线程2:" << p << std::endl;
	}
}

多线程间消息通讯

image-20211206102547281

image-20211206102625517

image-20211206102704984

image-20211206103117685

image-20211206103147736

image-20211206103202001

image-20211206103307643

image-20211206103338290

image-20211206111245660

#include <windows.h>
#include <iostream>
#include <process.h>

DWORD WINAPI ThreadFun1(LPVOID param);
DWORD WINAPI ThreadFun2(LPVOID param);
//自定义消息(必须是自定义消息+1)
#define MY_MSG WM_USER+1
int main()
{
	DWORD threadID = 0;
	//获取第一个线程的ID,方便第二个线程给第一个线程发消息
	HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, &threadID);
	HANDLE hThread2 = CreateThread(NULL, 0, ThreadFun2, (LPVOID)threadID, 0, NULL);
	HANDLE hArr[] = { hThread1,hThread2 };
	WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
	return 0;
}
DWORD WINAPI ThreadFun1(LPVOID param)
{
	//接收第二个线程发来的消息
	MSG msg;
	while (GetMessage(&msg,NULL,0,0))//如果有消息继续,否则就阻塞
	{
		switch (msg.message)
		{
		case MY_MSG:
			std::cout << "收到消息:" << msg.wParam << std::endl;
			break;
		}
		
	}
	std::cout << "收到退出消息:" <<  std::endl;
	return 0;
    //利用PeekMessage
	//MSG msg;
	//while (true)
	//{
	//	//马上就返回,不阻塞
	//	if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	//	{
	//		switch (msg.message)
	//		{
	//		case MY_MSG:
	//			std::cout << "收到消息:" << msg.wParam << std::endl;
	//			break;
	//		case WM_QUIT:
	//			std::cout << "收到QUIT消息" << std::endl;
	//			return 0;
	//		}
	//	}
	//}
}
DWORD WINAPI ThreadFun2(LPVOID param)
{
	//给第一个线程发消息
	DWORD threadID = (DWORD)param;
	int N = 1;
	while (true)
	{
		if (N==10)
		{
			//让第一个线程退出消息循环
			PostThreadMessage(threadID, WM_QUIT, (WPARAM)N++, NULL);
			break;
		}
		PostThreadMessage(threadID, MY_MSG, (WPARAM)N++, NULL);
		Sleep(500);
	}
	return 0;
}

C++11 多线程

image-20211206185738238

image-20211206185905748

image-20211206185914875

image-20211206185942141

image-20211206190017014

image-20211206190035139

thread 线程类

image-20211206190206535

image-20211206190455019

image-20211206190600232

image-20211206190611831

image-20211206190618168

image-20211206190657051

image-20211206190726132

image-20211206192748593

#include <thread>
#include <string>
#include <iostream>

using namespace std;

void ThreadFun(const string &s)
{
	cout << s.c_str() << endl;
}

int main()
{
	//默认构造函数
	thread t1;
	cout << t1.get_id() << endl;//为0
	cout << t1.joinable() << endl;//为0
	
	thread t2(ThreadFun, "dddd");
	cout << t2.get_id() << endl;//为0
	cout << t2.joinable() << endl;//为0
	t2.join();//等待

	getchar();
}

this_thread命名空间

image-20211207120003344

image-20211207120012737

image-20211207120032687

image-20211207120150502

image-20211207120201385

image-20211207120211596

image-20211207120243397

#include <iostream>
#include <thread>
#include <string>

using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
void ThreadFun(const string& str)
{
	cout << "线程ID:" << get_id() << endl;//获取线程ID
	while (true)
	{
		cout << str << endl;
		//sleep_for(seconds(1));//休眠1s
		sleep_until(system_clock::now() + milliseconds(1000));//当前时间加上1s
	}
}
int main()
{
	thread t1(ThreadFun, "hello");
	cout <<"线程ID:"<< t1.get_id() << endl;
	t1.join();
}

atomic 类与 atomic_flag类

image-20211207140223322

image-20211207140232321

image-20211207140255336

image-20211207140335234

image-20211207140428026

#include <iostream>
#include <thread>
#include <string>
#include <atomic>

using namespace std;

atomic<int> N = 0;
void ThreadFun()
{
	for (size_t i = 0; i < 10000; i++)
	{
		++N;//这样保证了原子操作,如果不用atomic则可能得到的数不是20000
	}
}
int main()
{
	thread t1(ThreadFun);
	thread t2(ThreadFun);
	
	t1.join();
	t2.join();
	cout << N << endl;
}

image-20211207141417336

#include <iostream>
#include <thread>
#include <string>
#include <atomic>
#include <vector>

using namespace std;
atomic<bool> ready = false;
atomic_flag win = ATOMIC_FLAG_INIT;
void Run(int id)
{
	while (!ready)//枪没响,不能跑
	{
		this_thread::yield();//让其他线程先执行
	}
	for (size_t i = 0; i < 100000; i++)
	{
		//无需执行,表示跑的过程
	}
	//如果没有被设置过,返回false
	if (!win.test_and_set())//调用后会自动设置,则会返回true
	{
		cout << id << "赢得第一" << endl;
	}
}
int main()
{
	//十个选手赛跑
	vector<thread> vecPlayers;
	for (size_t i = 0; i < 10; i++)
	{
		vecPlayers.push_back(thread(Run,i));
	}
	cout << "10个选手已经准备"<< endl;
	//预备跑
	this_thread::sleep_for(chrono::seconds(3));
	cout << "3 2 1预备跑" << endl;
	ready = true;
	for (thread& t :vecPlayers)
	{
		t.join();
	}
}

互斥类mutex

image-20211207143933799

image-20211207143946720

image-20211207144025082

image-20211207144206499

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

using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
int tickets = 100;
mutex m;
void SellThread(const string& str)
{
	while (tickets>0)
	{
		m.lock();//加锁
		if (tickets>0)
		{
			sleep_for(milliseconds(100));
			cout<<str<<"卖出" <<tickets-- <<"票" << endl;
		}
		m.unlock();//解锁
	}
}
int main()
{
	thread t1(SellThread, "售票窗口A");
	thread t2(SellThread, "售票窗口B");
	t1.join();
	t2.join();
}

image-20211207151520764

//递归加锁就是多次加锁,也要多次解锁
recursive_mutex m;
void SellThread(const string& str)
{
	while (tickets>0)
	{
		m.lock();//加锁
		m.lock();
		if (tickets>0)
		{
			sleep_for(milliseconds(10));
			cout<<str<<"卖出" <<tickets-- <<"票" << endl;
		}
		m.unlock();//解锁
		m.unlock();//解锁
	}
}

image-20211207151851297

image-20211207151926496

image-20211207151932338

timed_mutex m;//指定锁住时间
void SellThread(const string& str)
{
	while (tickets>0)
	{
		m.try_lock_for(milliseconds(10));//锁住10ms
		if (tickets>0)
		{
			sleep_for(milliseconds(10));
			cout<<str<<"卖出" <<tickets-- <<"票" << endl;
		}
		//会自动解锁
	}
}

image-20211207152220423

lock_guard类

image-20211207152315977

image-20211207152322652

image-20211207152623718

image-20211207152705375

image-20211207152740038

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

using namespace std;
using namespace std::this_thread;
using namespace std::chrono;

mutex m;
void FunThread1()
{
	try
	{
		for (size_t i = 0; i < 10; i++)
		{
			sleep_for(chrono::seconds(1));
			//m.lock();
			lock_guard<mutex> lck(m);//局部作用域
			if (i == 3)
			{
				throw logic_error("发生异常");
			}
			cout << "A打印" << i << endl;
			//m.unlock();//抛出异常,导致无法解锁
		}
	}
	catch (const std::exception& e)
	{
		cout << "捕捉异常:" << e.what() << endl;
	}
	
}
void FunThread2()
{
	for (size_t i = 0; i < 10; i++)
	{
		sleep_for(chrono::seconds(1));
		//m.lock();
		lock_guard<mutex> lck(m);
		cout << "B打印" << i << endl;
		//m.unlock();
	}
}
int main()
{
	thread t1(FunThread1);
	thread t2(FunThread2);
	t1.join();
	t2.join();
}

image-20211207154306872

unique_lock类

image-20211207154906551

image-20211207154924297

image-20211207155026264

image-20211207155154904

image-20211207155252667

image-20211207155304663

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

using namespace std;
using namespace std::this_thread;
using namespace std::chrono;

mutex m;
void FunThread1()
{
	try
	{
		for (size_t i = 0; i < 10; i++)
		{
			sleep_for(chrono::seconds(1));
			//m.lock();
			unique_lock<mutex> lck(m);
			if (i == 3)
			{
				throw logic_error("发生异常");
			}
			cout << "A打印" << i << endl;
			lck.unlock();//更加灵活的控制范围
			//m.unlock();//抛出异常,导致无法解锁
		}
	}
	catch (const std::exception& e)
	{
		cout << "捕捉异常:" << e.what() << endl;
	}
	
}
void FunThread2()
{
	for (size_t i = 0; i < 10; i++)
	{
		sleep_for(chrono::seconds(1));
		//m.lock();
		unique_lock<mutex> lck(m);
		cout << "B打印" << i << endl;
		//m.unlock();
	}
}
int main()
{
	thread t1(FunThread1);
	thread t2(FunThread2);
	t1.join();
	t2.join();
}

conditon_variable类

image-20211207162823787

image-20211207162830967

image-20211207162838066

image-20211207162937970

image-20211207163028096

image-20211207163202180

image-20211207163246500

image-20211207163258687

image-20211207163308043

image-20211207163727802

image-20211207163745197

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

using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
//condition_variable cv;//仅仅支持unique_lock<mutex>作为wait的参数
condition_variable_any cv;//接受任何lockable参数作为wait的参数
mutex m;
void FunThread1(int id)
{
	unique_lock<mutex> lck(m);
	cv.wait(lck);//等待被唤醒
	cout << "线程ID:" << id << "执行!" << endl;
	
}
int main()
{
	thread t1(FunThread1, 1);
	thread t2(FunThread1, 2);
	thread t3(FunThread1,3);
	cout << "3s后唤醒" << endl;
	sleep_for(seconds(3));//3s之后唤醒所有的线程
	//cv.notify_all();//唤醒所有的线程
	cv.notify_one();//只唤醒1个,唤醒那个事随机的
	t1.join();
	t2.join();
	t3.join();
}

future类

image-20211208090928953

image-20211208090951013

image-20211208091111840

image-20211208091235353

image-20211208091334281

image-20211208091405788

image-20211208091428659

#include <iostream>
#include<future>
#include <thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
int sum(int a, int b)//设置费时的加法操作
{
	cout << "子线程开始计算" << endl;
	sleep_for(seconds(3));
	cout << "子线程算出结果" << endl;
	return a + b;
}
int main()
{
	cout << "主线程开始" << endl;
	future<int> result = async(sum, 123, 456);
	result.wait();//等待结果算出
	int s= result.get();//得到结果
	cout << "结果是:" << s << endl;
	cout << "主线程结束" << endl;
}

promise类

image-20211208092311884

image-20211208092319982

image-20211208092414892

image-20211208092442449

image-20211208092519196

#include <iostream>
#include<future>
#include <thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
void Work(promise<int>&prom)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(5));
	//设置结果,future会get到
	prom.set_value(666);
}
int main()
{
	promise<int> prom;//定义一个promise
	//future和promise搭配使用,类似于anysc
	future<int> result = prom.get_future();
	thread t1(Work,ref(prom));
	t1.detach();
	int s= result.get();
	cout << "获取结果" << s << endl;
}

image-20211208093431102

#include <iostream>
#include<future>
#include <thread>
#include <exception>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
void Work(promise<int>&prom)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(5));
	try
	{
		throw runtime_error("超时");
	}
	catch (const std::exception& e)
	{
		//设置异常
		prom.set_exception(current_exception());
	}
	
}
int main()
{
	promise<int> prom;//定义一个promise
	//future和promise搭配使用,类似于anysc
	future<int> result = prom.get_future();
	thread t1(Work,ref(prom));
	t1.detach();
	try
	{
		int s = result.get();
	}
	catch (const std::exception&  e)
	{
		cout << "结果异常" << e.what() << endl;
	}
}

packaged_task类

image-20211208095115576

image-20211208095135417

image-20211208095201881

image-20211208095252045

#include <iostream>
#include<future>
#include <thread>
#include <exception>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
int Work(int a,int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	return  a + b;
}
int main()
{
	//packaged_task包装了一个可调用的目标
	packaged_task<int(int, int)>pack(Work);
	future<int> result = pack.get_future();//获取packaged_task内部的future
	thread t1(move(pack), 12, 34);//将package_task给线程执行
	t1.detach();
	int sum = result.get();
	cout << "获取结果" << sum << endl;
}

总结

image-20211208101141462

image-20211208101326314

image-20211208101445406

image-20211208101540756

#include <iostream>
#include<future>
#include <thread>
#include <exception>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
void Work1(promise<int>& prom,int a,int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	prom.set_value(a + b);
}
int Work2( int a, int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	return a + b;
}
int Work3(int a, int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	return a + b;
}
int main()
{
	promise<int> prom;//promise内部包装了一个值
	future<int> f1 = prom.get_future();//使用成员函数获取future
	thread(Work1, ref(prom), 1, 2).detach();
	f1.wait();
	cout << "计算结果:" << f1.get() << endl;

	packaged_task<int(int, int)>task(Work2);
	future<int> f2 = task.get_future();
	thread(move(task), 11, 22).detach();
	f2.wait();
	cout << "计算结果:" << f2.get() << endl;

	future<int> f3 = async(Work3, 111, 222);
	f3.wait();
	cout << "计算结果:" << f3.get() << endl;
}
```cpp

nt Work(int a,int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	return  a + b;
}
int main()
{
	//packaged_task包装了一个可调用的目标
	packaged_task<int(int, int)>pack(Work);
	future<int> result = pack.get_future();//获取packaged_task内部的future
	thread t1(move(pack), 12, 34);//将package_task给线程执行
	t1.detach();
	int sum = result.get();
	cout << "获取结果" << sum << endl;
}

总结

#include <iostream>
#include<future>
#include <thread>
#include <exception>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
void Work1(promise<int>& prom,int a,int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	prom.set_value(a + b);
}
int Work2( int a, int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	return a + b;
}
int Work3(int a, int b)//费时操作
{
	cout << "开始计算" << endl;
	sleep_for(seconds(3));
	return a + b;
}
int main()
{
	promise<int> prom;//promise内部包装了一个值
	future<int> f1 = prom.get_future();//使用成员函数获取future
	thread(Work1, ref(prom), 1, 2).detach();
	f1.wait();
	cout << "计算结果:" << f1.get() << endl;

	packaged_task<int(int, int)>task(Work2);
	future<int> f2 = task.get_future();
	thread(move(task), 11, 22).detach();
	f2.wait();
	cout << "计算结果:" << f2.get() << endl;

	future<int> f3 = async(Work3, 111, 222);
	f3.wait();
	cout << "计算结果:" << f3.get() << endl;
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

步、步、为营

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值