windows多线程程序设计(基础篇) 您所在的位置:网站首页 Windows多线程开发 windows多线程程序设计(基础篇)

windows多线程程序设计(基础篇)

2024-01-09 16:47| 来源: 网络整理| 查看: 265

基础篇包括了4个小内容。

1.基本的线程操作

2.线程对象封装

3.互斥和临界区

4.同步操作

1.基本的线程操作

线程函数

 win32c创建线程CreateThread

_beginthread

_beginthreadex

恢复线程

ResumeThread 

挂起线程

SuspendThread 

退出线程

ExitThread

_endthread

_endthreadex

强制结束线程

TerminateThread 

释放线程对象

CloseHandle 设置线程优先级SetThreadPriority 

线程回调函数

ThreadProc 

Demo1

#include #include #include unsigned __stdcall MyThreadFunc(void* p) { printf("线程启动,停留3秒\n"); Sleep(3000); printf("线程退出\n"); _endthreadex(0); // c语言退出线程函数 return 0; } int main() { HANDLE hThread; unsigned threadID; hThread = (HANDLE)_beginthreadex( // c语言创建线程函数 NULL, // 安全属性 0, // 线程堆栈大小 &MyThreadFunc, // 函数指针,指向线程函数 NULL, // 函数参数,输入到线程函数 0, // 新线程的初始状态,0表示立即执行,CREATE_SUSPENDED 表示创建之后挂起 &threadID); // 返回线程ID DWORD dw = WaitForSingleObject(hThread, // 资源句柄, 这里是线程的句柄 INFINITE); // INFINITE-无线等待 数字-等待时长(毫秒) switch (dw) // 返回值 { case WAIT_OBJECT_0: // 等到第0个对象 break; case WAIT_TIMEOUT: // 等待超时 break; case WAIT_FAILED: // 输入句柄错误 break; } CloseHandle(hThread); system("Pause"); return 0; } 2.线程对象封装

通过封装可以定义自己的线程类

Demo2

#include #include DWORD WINAPI ThreadFunWrapper(LPVOID lpParam); class MyThread { public: HANDLE hSendthread; MyThread(void); ~MyThread(void); void StartThread(); void StopThread(); void ThreadFun(); }; MyThread::MyThread(void) // 创建线程 { hSendthread = CreateThread(0, 0, ThreadFunWrapper, // ThreadFun()是类成员函数,createthread不能接受成员函数的指针,所以需要创建一个封装函数。 this, // 实例指针,传递给封装函数 CREATE_SUSPENDED, 0); }; MyThread::~MyThread(void) { TerminateThread(hSendthread, 0); // 强制删除线程 CloseHandle(hSendthread); }; void MyThread::StartThread() { ResumeThread(hSendthread); }; void MyThread::StopThread() { SuspendThread(hSendthread); }; void MyThread::ThreadFun() { printf("线程启动,停留3秒\n"); Sleep(3000); printf("线程退出\n"); ExitThread(0); // windows api线程结束函数 }; DWORD WINAPI ThreadFunWrapper(LPVOID lpParam) // 封装函数 { MyThread * pMyThread = reinterpret_cast(lpParam); pMyThread->ThreadFun(); return 0; } int main() { MyThread tr; // 默认创建的线程是挂起状态 tr.StartThread(); // 从挂起状态恢复 WaitForSingleObject(tr.hSendthread,10000); // 等待线程退出 system("Pause"); return 0; } 3.互斥和临界区  互斥临界区类型

HANDLE   hMutex 

CRITICAL_SECTION g_cs;

创建

CreateMutex

InitializeCriticalSection(&g_cs);

释放

CloseHandle

DeleteCriticalSection(&g_cs);

进入lock

WaitForSingleObject

WaitForMultipleObjects

EnterCriticalSection(&g_cs);

离开unlock

ReleaseMutex

LeaveCriticalSection(&g_cs);

Mutex可以和waitfor系列函数搭配使用,且支持跨进程,功能强大。CriticalSection容易理解使用较为简单。

demo3

#include #include #include CRITICAL_SECTION g_cs; unsigned __stdcall MyThreadFunc(void* pArguments) { // EnterCriticalSection(&g_cs); // 进入临界区 for (int i = 0; i < 100; i++) putchar('0' + *(int*)pArguments); putchar('\n'); // LeaveCriticalSection(&g_cs); // 退出临界区 _endthreadex(0); return 0; } int main() { HANDLE hThread[5]; unsigned threadID[5]; int id[5] = { 1, 2, 3, 4, 5 }; InitializeCriticalSection(&g_cs); int i; for (i = 0; i < 5; i++) hThread[i] = (HANDLE)_beginthreadex(NULL, 0, &MyThreadFunc, &id[i], 0, &threadID[i]); DWORD dw = WaitForMultipleObjects( // 等所有线程完成工作 5, // 等待事件的总数量 hThread, // 事件数组 TRUE, // TRUE-等待全部事件 FALSE-等待任一事件 10000); // 最长等待多长事件 switch (dw) // 处理返回值 { case WAIT_OBJECT_0 + 0: break; case WAIT_OBJECT_0 + 1: break; case WAIT_OBJECT_0 + 2: break; case WAIT_OBJECT_0 + 3: break; case WAIT_OBJECT_0 + 4: break; case WAIT_TIMEOUT: break; case WAIT_FAILED: break; default: break; } for (i = 0; i < 5; i++) // 释放所有线程句柄 CloseHandle(hThread[i]); DeleteCriticalSection(&g_cs); system("Pause"); return 0; } 4.同步操作  信号量事件初始化CreateSemaphoreCreateEvent

获取访问权

OpenSemaphoreOpenEvent

P操作

WaitForSingleObject

WaitForMultipleObjects

WaitForSingleObject

WaitForMultipleObjects

V操作

ReleaseSemaphoreSetEvent

信号量支持多个资源,类似操作系统中的记录型信号量,可用于多个同类型资源管理。event事件主要用于实现操作同步。

Demo4同步

下例中有两组同步关系,停车|开门,关门|开车。用两个event分别表示。

加入PV操作后可得,停车V(s1)|P(s1)开门,关门V(s2)|P(s2)开车。

#include #include HANDLE hevent1, hevent2; HANDLE hevent_exit; DWORD WINAPI SellerThreadFunc(void* p); DWORD WINAPI DriverThreadFunc(void* p); int main() { CreateMutex(NULL, FALSE, NULL); srand(342443); DWORD sellerthreadid, driverthreadid; // CreateEvent函数说明 // 参数2 指定将事件对象创建成手动复原还是自动复原。FALSE-自动复位,当一个等待线程(WaitForSingleObject)被释放以后自动将事件状态复位到无信号状态。TRUE - 人工复位,调用ResetEvent函数将事件的状态复位到无信号状态。 // 参数3 指定事件对象的初始状态。TRUE-初始状态为有信号状态;FALSE-初始状态为无信号状态。 hevent1 = CreateEvent(NULL, TRUE, FALSE, _T("s1")); // event对象为人工复位模式 hevent2 = CreateEvent(NULL, FALSE, FALSE, _T("s2")); // event对象为自动复位模式 hevent_exit = CreateEvent(NULL, TRUE, FALSE, _T("ext"));// 人工复位的事件,初始状态为有信号状态 HANDLE h[2]; h[0] = CreateThread(0, 0, SellerThreadFunc, NULL, 0, &sellerthreadid); h[1] = CreateThread(0, 0, DriverThreadFunc, NULL, 0, &driverthreadid); Sleep(10000); // 20秒后发送结束信号 SetEvent(hevent_exit); // 人工复位的事件,初始状态为有信号状态 WaitForMultipleObjects(2, h, TRUE, INFINITE); // 等待所有线程退出 CloseHandle(hevent1); CloseHandle(hevent2); CloseHandle(hevent_exit); CloseHandle(h[0]); CloseHandle(h[1]); system("Pause"); return 0; } DWORD WINAPI SellerThreadFunc(void* p) { while (1) { Sleep(rand() % 1000); printf("售票员: 关门 V(s2)\n"); SetEvent(hevent1); Sleep(rand() % 1000); printf("售票员: 售票\n"); Sleep(rand() % 1000); // 随机等待0~999毫秒 WaitForSingleObject(hevent2, INFINITE); printf("售票员: 开门 P(s1)\n"); DWORD dw = WaitForSingleObject(hevent_exit, 0); // 检测结束事件,不等待。 if (dw == WAIT_OBJECT_0) // 如果是结束事件则退出线程。 ExitThread(0); } } DWORD WINAPI DriverThreadFunc(void* p) { while (1) { WaitForSingleObject(hevent1, INFINITE); ResetEvent(hevent1); // event对象为人工复位模式 Sleep(rand() % 1000); printf("司 机: 开车 P(s2)\n"); Sleep(rand() % 1000); printf("司 机: 驾驶\n"); Sleep(rand() % 1000); printf("司 机: 停车 V(s1)\n"); SetEvent(hevent2); DWORD dw = WaitForSingleObject(hevent_exit, 0); if (dw == WAIT_OBJECT_0) ExitThread(0); } }

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有