gpt4 book ai didi

C++ 如何实现多线程与线程同步

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 24 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章C++ 如何实现多线程与线程同步由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

CreateThread 实现多线程:

先来创建一个简单的多线程实例,无参数传递版,运行实例会发现,主线程与子线程运行无规律.

#include <windows.h>#include <iostream>using namespace std;DWORD WINAPI Func(LPVOID lpParamter){	for (int x = 0; x < 10; x++)	{		cout << "thread function" << endl;		Sleep(200);	}	return 0;}int main(int argc,char * argv[]){	HANDLE hThread = CreateThread(NULL, 0, Func, NULL, 0, NULL);	CloseHandle(hThread);	for (int x = 0; x < 10; x++)	{		cout << "main thread" << endl;		Sleep(400);	}	system("pause");	return 0;}

  。

beginthreadex 实现多线程:

这个方法与前面的CreateThread使用完全一致,只是在参数上面应使用void *该参数可以强转为任意类型,两者实现效果完全一致.

#include <windows.h>#include <iostream>#include <process.h>using namespace std;unsigned WINAPI Func(void *arg){	for (int x = 0; x < 10; x++)	{		cout << "thread function" << endl;		Sleep(200);	}	return 0;}int main(int argc, char * argv[]){	HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, Func, NULL, 0, NULL);	CloseHandle(hThread);	for (int x = 0; x < 10; x++)	{		cout << "main thread" << endl;		Sleep(400);	}	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

  。

CreateMutex 互斥锁实现线程同步:

使用互斥锁可以实现单位时间内,只允许一个线程拥有对共享资源的独占,从而实现了互不冲突的线程同步.

#include <windows.h>#include <iostream>using namespace std;HANDLE hMutex = NULL;   // 创建互斥锁// 线程函数DWORD WINAPI Func(LPVOID lpParamter){	for (int x = 0; x < 10; x++)	{		// 请求获得一个互斥锁		WaitForSingleObject(hMutex, INFINITE);		cout << "thread func" << endl;		// 释放互斥锁		ReleaseMutex(hMutex);	}	return 0;}int main(int argc,char * argv[]){	HANDLE hThread = CreateThread(NULL, 0, Func, NULL, 0, NULL);	hMutex = CreateMutex(NULL, FALSE, "lyshark");	CloseHandle(hThread);	for (int x = 0; x < 10; x++)	{		// 请求获得一个互斥锁		WaitForSingleObject(hMutex, INFINITE);		cout << "main thread" << endl;				// 释放互斥锁		ReleaseMutex(hMutex);	}	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

通过互斥锁,同步执行两个线程函数.

#include <windows.h>#include <iostream>using namespace std;HANDLE hMutex = NULL;   // 创建互斥锁#define NUM_THREAD 50// 线程函数1DWORD WINAPI FuncA(LPVOID lpParamter){	for (int x = 0; x < 10; x++)	{		// 请求获得一个互斥锁		WaitForSingleObject(hMutex, INFINITE);		cout << "this is thread func A" << endl;		// 释放互斥锁		ReleaseMutex(hMutex);	}	return 0;}// 线程函数2DWORD WINAPI FuncB(LPVOID lpParamter){	for (int x = 0; x < 10; x++)	{		// 请求获得一个互斥锁		WaitForSingleObject(hMutex, INFINITE);		cout << "this is thread func B" << endl;		// 释放互斥锁		ReleaseMutex(hMutex);	}	return 0;}int main(int argc, char * argv[]){	// 用来存储线程函数的句柄	HANDLE tHandle[NUM_THREAD];	// /创建互斥量,此时为signaled状态	hMutex = CreateMutex(NULL, FALSE, "lyshark");	for (int x = 0; x < NUM_THREAD; x++)	{		if (x % 2)		{			tHandle[x] = CreateThread(NULL, 0, FuncA, NULL, 0, NULL);		}		else		{			tHandle[x] = CreateThread(NULL, 0, FuncB, NULL, 0, NULL);		}	}	// 等待所有线程函数执行完毕	WaitForMultipleObjects(NUM_THREAD, tHandle, TRUE, INFINITE);		// 销毁互斥对象	CloseHandle(hMutex);	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

  。

通过临界区实现线程同步:

临界区与互斥锁差不多,临界区使用时会创建CRITICAL_SECTION临界区对象,同样相当于一把钥匙,线程函数执行结束自动上交,如下是临界区函数的定义原型.

//初始化函数原型VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);//销毁函数原型VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);//获取VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);//释放VOID LeaveCriticalSection(  LPCRITICAL_SECTION lpCriticalSection);

这一次我们不适用互斥体,使用临界区实现线程同步,结果与互斥体完全一致,看个人喜好.

#include <windows.h>#include <iostream>using namespace std;CRITICAL_SECTION cs;         // 全局定义临界区对象#define NUM_THREAD 50// 线程函数DWORD WINAPI FuncA(LPVOID lpParamter){	for (int x = 0; x < 10; x++)	{		//进入临界区		EnterCriticalSection(&cs);		cout << "this is thread func A" << endl;		//离开临界区		LeaveCriticalSection(&cs);	}	return 0;}int main(int argc, char * argv[]){	// 用来存储线程函数的句柄	HANDLE tHandle[NUM_THREAD];	//初始化临界区	InitializeCriticalSection(&cs);	for (int x = 0; x < NUM_THREAD; x++)	{		tHandle[x] = CreateThread(NULL, 0, FuncA, NULL, 0, NULL);	}	// 等待所有线程函数执行完毕	WaitForMultipleObjects(NUM_THREAD, tHandle, TRUE, INFINITE);		//释放临界区	DeleteCriticalSection(&cs);	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

  。

Semaphore 基于信号实现线程同步:

通过定义一个信号,初始化信号为0,利用信号量值为0时进入non-signaled状态,大于0时进入signaled状态的特性即可实现线程同步.

#include <windows.h>#include <iostream>using namespace std;static HANDLE SemaphoreOne;static HANDLE SemaphoreTwo;// 线程函数1DWORD WINAPI FuncA(LPVOID lpParamter){	for (int x = 0; x < 10; x++)	{		// 临界区开始时设置 signaled 状态		WaitForSingleObject(SemaphoreOne, INFINITE);		cout << "this is thread func A" << endl;		// 临界区结束则设置为 non-signaled 状态		ReleaseSemaphore(SemaphoreOne, 1, NULL);	}	return 0;}// 线程函数2DWORD WINAPI FuncB(LPVOID lpParamter){	for (int x = 0; x < 10; x++)	{		// 临界区开始时设置 signaled 状态		WaitForSingleObject(SemaphoreTwo, INFINITE);		cout << "this is thread func B" << endl;		// 临界区结束则设置为 non-signaled 状态		ReleaseSemaphore(SemaphoreTwo, 1, NULL);	}	return 0;}int main(int argc, char * argv[]){	// 用来存储线程函数的句柄	HANDLE hThreadA, hThreadB;	// 创建信号量对象,并且设置为0进入non-signaled状态 	SemaphoreOne = CreateSemaphore(NULL, 0, 1, NULL);	// 创建信号量对象,并且设置为1进入signaled状态	SemaphoreTwo = CreateSemaphore(NULL, 1, 1, NULL);       // 先执行这一个线程函数	hThreadA = CreateThread(NULL, 0, FuncA, NULL,0, NULL);	hThreadB = CreateThread(NULL, 0, FuncB, NULL, 0, NULL);	// 等待两个线程函数执行完毕	WaitForSingleObject(hThreadA, INFINITE);	WaitForSingleObject(hThreadA, INFINITE);	// 销毁两个线程函数	CloseHandle(SemaphoreOne);	CloseHandle(SemaphoreTwo);	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

上面的一段代码,容易产生死锁现象,即,线程函数B执行完成后,A函数一直处于等待状态.

执行WaitForSingleObject(semTwo, INFINITE);会让线程函数进入类似挂起的状态,当接到ReleaseSemaphore(semOne, 1, NULL);才会恢复执行.

#include <windows.h>  #include <stdio.h>  static HANDLE semOne,semTwo;static int num;// 线程函数A用于接收参书DWORD WINAPI ReadNumber(LPVOID lpParamter){	int i;	for (i = 0; i < 5; i++)	{		fputs("Input Number: ", stdout);		//临界区的开始 signaled状态  		WaitForSingleObject(semTwo, INFINITE);				scanf("%d", &num);		//临界区的结束 non-signaled状态  		ReleaseSemaphore(semOne, 1, NULL);	}	return 0;}// 线程函数B: 用户接受参数后完成计算DWORD WINAPI Check(LPVOID lpParamter){	int sum = 0, i;	for (i = 0; i < 5; i++)	{		//临界区的开始 non-signaled状态  		WaitForSingleObject(semOne, INFINITE);		sum += num;		//临界区的结束 signaled状态  		ReleaseSemaphore(semTwo, 1, NULL);	}	printf("The Number IS: %d \n", sum);	return 0;}int main(int argc, char *argv[]){	HANDLE hThread1, hThread2;	//创建信号量对象,设置为0进入non-signaled状态  	semOne = CreateSemaphore(NULL, 0, 1, NULL);	//创建信号量对象,设置为1进入signaled状态  	semTwo = CreateSemaphore(NULL, 1, 1, NULL);	hThread1 = CreateThread(NULL, 0, ReadNumber, NULL, 0, NULL);	hThread2 = CreateThread(NULL, 0, Check, NULL, 0, NULL);	// 关闭临界区	WaitForSingleObject(hThread1, INFINITE);	WaitForSingleObject(hThread2, INFINITE);	CloseHandle(semOne);	CloseHandle(semTwo);	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

  。

CreateEvent 事件对象的同步:

事件对象实现线程同步,与前面的临界区和互斥体有很大的不同,该方法下创建对象时,可以在自动non-signaled状态运行的auto-reset模式,当我们设置好我们需要的参数时,可以直接使用SetEvent(hEvent)设置事件状态,会自动执行线程函数.

#include <windows.h>  #include <stdio.h>  #include <process.h>  #define STR_LEN 100  // 存储全局字符串static char str[STR_LEN];// 设置事件句柄static HANDLE hEvent;// 统计字符串中是否存在Aunsigned WINAPI NumberOfA(void *arg){	int cnt = 0;	// 等待线程对象事件	WaitForSingleObject(hEvent, INFINITE);	for (int i = 0; str[i] != 0; i++)	{		if (str[i] == 'A')			cnt++;	}	printf("Num of A: %d \n", cnt);	return 0;}// 统计字符串总长度unsigned WINAPI NumberOfOthers(void *arg){	int cnt = 0;	// 等待线程对象事件	WaitForSingleObject(hEvent, INFINITE);	for (int i = 0; str[i] != 0; i++)	{		if (str[i] != 'A')			cnt++;	}	printf("Num of others: %d \n", cnt - 1);	return 0;}int main(int argc, char *argv[]){	HANDLE hThread1, hThread2;	// 以non-signaled创建manual-reset模式的事件对象	// 该对象创建后不会被立即执行,只有我们设置状态为Signaled时才会继续	hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);	hThread1 = (HANDLE)_beginthreadex(NULL, 0, NumberOfA, NULL, 0, NULL);	hThread2 = (HANDLE)_beginthreadex(NULL, 0, NumberOfOthers, NULL, 0, NULL);	fputs("Input string: ", stdout);	fgets(str, STR_LEN, stdin);	// 字符串读入完毕后,将事件句柄改为signaled状态  	SetEvent(hEvent);	WaitForSingleObject(hThread1, INFINITE);	WaitForSingleObject(hThread2, INFINITE);	//non-signaled 如果不更改,对象继续停留在signaled	ResetEvent(hEvent);	CloseHandle(hEvent);	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

  。

线程函数传递单个参数:

线程函数中的定义中LPVOID允许传递一个参数,只需要在县城函数中接收并强转(int)(LPVOID)port即可.

#include <stdio.h>#include <Windows.h>// 线程函数接收一个参数DWORD WINAPI ScanThread(LPVOID port){	// 将参数强制转化为需要的类型	int Port = (int)(LPVOID)port;	printf("[+] 端口: %5d \n", port);	return 1;}int main(int argc, char* argv[]){	HANDLE handle;	for (int port = 0; port < 100; port++)	{		handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ScanThread, (LPVOID)port, 0, 0);	}	WaitForSingleObject(handle, INFINITE);	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

  。

线程函数传递多参数:

如果想在线程函数中传递多个参数,则需要传递一个结构指针,通过线程函数内部强转为结构类型后,取值,这个案例花费了我一些时间,网上也没找到合适的解决方法,或找到的都是歪瓜裂枣瞎转的东西,最后还是自己研究了一下写了一个没为题的.

其主要是线程函数中调用的参数会与下一个线程函数结构相冲突,解决的办法时在每次进入线程函数时,自己拷贝一份,每个人使用自己的那一份,才可以避免此类事件的发生,同时最好配合线程同步一起使用,如下时线程扫描器的部分代码片段.

#include <stdio.h>#include <windows.h>typedef struct _THREAD_PARAM{	char *HostAddr;             // 扫描主机	DWORD dwStartPort;          // 端口号}THREAD_PARAM;// 这个扫描线程函数DWORD WINAPI ScanThread(LPVOID lpParam){	// 拷贝传递来的扫描参数	THREAD_PARAM ScanParam = { 0 };	// 这一步很重要,如不拷贝,则会发生重复赋值现象,导致扫描端口一直都是一个。	// 坑死人的玩意,一开始我始终没有发现这个问题。sb玩意!!	MoveMemory(&ScanParam, lpParam, sizeof(THREAD_PARAM));	printf("地址: %-16s --> 端口: %-5d 状态: [Open] \n", ScanParam.HostAddr, ScanParam.dwStartPort);	return 0;}int main(int argc, char *argv[]){	THREAD_PARAM ThreadParam = { 0 };	ThreadParam.HostAddr = "192.168.1.10";	for (DWORD port = 1; port < 100; port++)	{		ThreadParam.dwStartPort = port;		HANDLE hThread = CreateThread(NULL, 0, ScanThread, (LPVOID)&ThreadParam, 0, NULL);		WaitForSingleObject(hThread, INFINITE);	}	system("pause");	return 0;}

C++ 如何实现多线程与线程同步

文章出处:https://www.cnblogs.com/lyshark 。

以上就是C++ 如何实现多线程与线程同步的详细内容,更多关于C++ 实现多线程与线程同步的资料请关注我其它相关文章! 。

原文链接:https://www.cnblogs.com/LyShark/p/13664972.html 。

最后此篇关于C++ 如何实现多线程与线程同步的文章就讲到这里了,如果你想了解更多关于C++ 如何实现多线程与线程同步的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com