C++多线程简单应用

一、C++多线程第一次总结,这里仅仅总结了std::thread和CreateThread用法,后续文章会更新全面的用法。为了编写方便,所有的用法解释都写在代码注释里面了。废话不多说,直接上代码。

// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <thread>
#include <string>
#include <windows.h>
#include <mutex>

//声明全局互斥量对象做线程同步
std::mutex mutexx;
//声明全局临界区对象做线程同步
CRITICAL_SECTION cs;
//结构体
struct MyStruct
{
    
    
	const std::string content;
	const int id;
};
void show1(const char str[], const int id)
{
    
    
	mutexx.lock();
	std::cout << "测试函数1线程: " << id << ",Output " << str << std::endl;
	Sleep(100);//必须包含#include <windows.h>才可以使用Sleep
	mutexx.unlock();
}

void show2(const char str[])
{
    
    
	EnterCriticalSection(&cs);
	std::cout << "测试函数2线程: " << ",Output " << str << std::endl;
	Sleep(500);
	LeaveCriticalSection(&cs);
}


DWORD WINAPI show3(LPVOID lpargs)
{
    
    
	EnterCriticalSection(&cs);
	MyStruct *p = (MyStruct *)lpargs;//转换为结构体指针
	std::cout << p->content << ",ID: " << p->id  << std::endl;
	Sleep(2000);
	LeaveCriticalSection(&cs);
	return 0;
}

//利用std::thread创建线程
void test1()
{
    
    
	//这种创建线程的方式,当线程创建完成,就会立马执行线程函数。
	//可以传递一个或者多个参数,std::thread t1(“函数名”, "函数参数1", “函数参数2”)
	//t1.join(); //表示同步(阻塞),调用线程走完,才能走后面的流程
	//t1.detach(); //表示异步(不会阻塞),主线程只触发此线程,后面和此线程无关
	std::thread t1(show1, "hello cplusplus!", 1);
	std::thread t2(show1, "你好,C++!", 2);
	std::thread t3(show1, "hello!", 3);
	t1.join(); t2.join(); t3.join();
	//t1.detach(); t2.detach(); t3.detach();
	std::cout << "测试函数1线程,一共三个线程全部执行完毕 " << std::endl;
	//调用t1.join(); t2.join(); t3.join();后
	//代码运行到这里,证明声明的三个线程已经全部运行完毕,后面代码可以综合三个线程的结果,执行后面的判断
}

//利用CreateThread创建线程
void test2()
{
    
    
	//注释:
	//这种创建线程的方式,当线程创建完成,可以选择立马执行或者先挂起后面再唤醒线程执行。
	//CreateThread默认只能传递一个参数。如果需要多个参数,可以声明函数时,传入结构体。
	//CreateThread的返回值是线程的句柄, 失败的话就返回NULL

	//CreateThread函数原型
	//HANDLE CreateThread(

	//	LPSECURITY_ATTRIBUTES lpThreadAttributes,

	//	DWORD dwStackSize,

	//	LPTHREAD_START_ROUTINE lpStartAddress,

	//	LPVOID lpParameter,

	//	DWORD dwCreationFlags,

	//	LPDWORD lpThreadID

	//);
	//第一个参数 lpThreadAttributes 表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。
	//第二个参数 dwStackSize 表示线程栈空间大小。传入0表示使用默认大小(1MB)。
	//第三个参数 lpStartAddress 表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
	//第四个参数 lpParameter 是传给线程函数的参数。
	//第五个参数 dwCreationFlags 指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。
	//第六个参数 lpThreadId 将返回线程的ID号,传入NULL表示不需要返回该线程ID号。


	//测试单个线程执行
	HANDLE hThread;
	DWORD threadId;
	MyStruct struct1{
    
    "单个线程执行传递多个参数的线程函数",1};
	hThread = CreateThread(NULL, 0, show3, &struct1, 0, &threadId);

	//注释:
	// WaitForSingleObject("线程句柄",“等待时间(单位ms)”)
	//WaitForSingleObject在等待时间内,线程执行完成,则返回0,否则返回值大于0
	//等待时间如果设置为INFINITE,则会阻塞直到对应线程执行完成。等待时间如果设置为0,则不会阻塞直接运行后续代码。如果设置1000,则线程阻塞1000ms后,执行后续代码。
	DWORD ret;
	ret = WaitForSingleObject(hThread, 2500);
	CloseHandle(hThread);
	std::cout << "单个线程全部执行完毕。 " << "规定时间内线程运行完成与否:" << ret << std::endl;
	//代码运行到这里,证明声明的三个线程已经全部运行完毕,后面代码可以综合三个线程的结果,执行后面的判断
	//*******************************************************************************************************************************


	//*******************************************************************************************************************************
	//测试多线程并发
	//注释:
	//DWORD WaitForMultipleObjects(

	//	DWORD nCount,             // number of handles in the handle array
	//	CONST HANDLE *lpHandles,  // pointer to the object-handle array
	//	BOOL fWaitAll,            // wait flag
	//	DWORD dwMilliseconds      // time-out interval in milliseconds
	//);
	//参数解析:
	//	DWORD 就是 Double Word, 每个word为2个字节的长度,DWORD双字即为4个字节,每个字节是8位。
	//	nCount  指定列表中的线程句柄数量  最大值为MAXIMUM_WAIT_OBJECTS(64)
	//	*lpHandles 线程句柄数组的指针(数组)。lpHandles为指定对象句柄组合中的第一个元素 HANDLE类型可以为(Event,Mutex,Process,Thread,Semaphore)数组
	//	bWaitAll 等待的类型,如果为TRUE,表示除非所有对象都发出信号(所有都执行完成),否则就一直等待下去;如果FALSE,表示任何一个对象发出信号即可
	//	dwMilliseconds指定要等候的毫秒数。如设为零,表示立即返回。如指定常数INFINITE,则可根据实际情况无限等待下去
	//WaitForMultipleObjects在等待时间内,线程执行完成,则返回0,否则返回值大于0
	const int thNum = 5;
	HANDLE hThread2[thNum];
	DWORD threadId2[thNum];
	for (int i = 0; i < thNum; i++)
	{
    
    
		MyStruct struct2{
    
     "多线程并发执行传递多个参数的线程函数",i };
		hThread2[i] = CreateThread(NULL, 0, show3, &struct2, 0, &threadId2[i]);
	}
	DWORD ret2;
	ret2 = WaitForMultipleObjects(thNum, hThread2, true, 100);
	for (int i = 0; i < thNum; i++)
	{
    
    
		CloseHandle(hThread2[i]);
	}
	std::cout << "多个线程并发全部执行完毕。 " << "规定时间内线程运行完成与否:" << ret2 << std::endl;
	//代码运行到这里,证明声明的三个线程已经全部运行完毕,后面代码可以综合三个线程的结果,执行后面的判断
}
int main()
{
    
    
	//初始化临界区对象
	//CRITICAL_SECTION结构对象必须经过InitializeCriticalSection()的初始化后才能使用
	InitializeCriticalSection(&cs);

	//多线程同步测试
	test1();
	test2();

	//清除临界区对象,释放资源
	DeleteCriticalSection(&cs);
	system("pause");
}

猜你喜欢

转载自blog.csdn.net/Douhaoyu/article/details/128683417