Win32编程之线程开发(八)
一、线程概念
(1).Windows线程是可以执行的代码的实例,系统是以线程为单位调度程序,一个程序当中可以有多个线程,实现多任务的处理
(2).Windows线程的特点:
- 线程都具有一个ID
- 每个线程都具有自己的内存栈
- 同一进程中的线程使用同一个地址空间
(3).线程的调度:操作系统将CPU的执行时间划分成时间片,依次根据时间片执行不同的线程,线程轮询:线程A->线程B->线程A...
二、线程的使用
1.创建线程
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, //安全属性
_In_ SIZE_T dwStackSize, //线程栈的大小
_In_ LPTHREAD_START_ROUTINE lpStartAddress, //线程处理函数的函数地址
_In_opt_ __drv_aliasesMem LPVOID lpParameter, //传递给线程处理函数的参数
_In_ DWORD dwCreationFlags, //线程的创建方式
_Out_opt_ LPDWORD lpThreadId //创建成功,返回线程的ID
);
创建成功,返回线程句柄
2.定义线程处理函数
DWORD WINAPI ThreadProc(
LPVOID lpParameter //创建线程时,传递给线程的参数
);
示例代码:
#include <Windows.h>
#include <iostream>
using namespace std;
DWORD CALLBACK ThreadProc(LPVOID lpThreadParameter) {
char* szText = (char*)lpThreadParameter;
while (true) {
cout << szText << endl;
Sleep(1000);
}
return 0;
}
int main() {
const char* pszText = "********";
DWORD nID = 0;
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)pszText, 0, &nID);
if (hThread == NULL) {
cout << "create thread failed" << GetLastError();
}
system("pause");
return 1;
}
三、线程的挂起和唤醒
(1).线程的挂起
DWORD SuspendThread( HANDLE hThread //handle to thread );
(2).线程的唤醒
DWORD ResumenThread( HANDLE hThread //handle to thread );
示例代码:
#include <Windows.h>
#include <iostream>
using namespace std;
DWORD CALLBACK ThreadProc(LPVOID lpThreadParameter) {
char* szText = (char*)lpThreadParameter;
while (true) {
cout << szText << endl;
Sleep(1000);
}
return 0;
}
DWORD CALLBACK ThreadProc1(LPVOID lpThreadParameter) {
char* szText = (char*)lpThreadParameter;
while (true) {
cout << szText << endl;
Sleep(1000);
}
return 0;
}
int main() {
const char* pszText = "********";
DWORD nID = 0;
//线程立即执行
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)pszText, 0, &nID);
if (hThread == NULL) {
cout << "create thread failed" << GetLastError();
}
const char* pszText1 = "--------";
DWORD nID1 = 0;
//线程挂起
HANDLE hThread1 = CreateThread(NULL, 0, ThreadProc1, (LPVOID)pszText1, CREATE_SUSPENDED, &nID1);
if (hThread1 == NULL) {
cout << "create thread failed" << GetLastError();
}
getchar();
SuspendThread(hThread);
ResumeThread(hThread1);
getchar();
return 1;
}
四、线程的销毁
(1).结束指定线程
BOOL TerminateThread( HANDLE hThread, //handle to thread DWORD dwExitCode //exit code );
(2).结束函数所在的线程
VOID ExitThread( DWORD dwExitCode //exit code for this thread );
五、线程的相关操作
(1).获取当前线程的ID:GetCurrentThreadId
(2).获取当前线程的句柄:GetCurrentThread
(3).等候单个句柄有信号:
VOID WaitForSingleObject( HANDLE handle, //句柄BUFF的地址 DWORD dwMilliseconds //等候时间INFINITE );
(3).同时等候多个句柄有信号
VOID WaitForMultipleObjects( DWORD nCount, //句柄数量 CONST HANDLE *lpHandle, //句柄BUFF的地址 BOOL bWait, //等候方式 DWORD dwMilliseconds //等候时间INFINITE ); bWaitAll(等候方式): TRUE:表示所有句柄都有信号,才结束等候 FALSE:表示句柄中只要有1个有信号,就结束等候
线程处于执行状态时,线程句柄没有信号,当线程结束的那一刻,线程句柄才有信号
示例代码:
#include <Windows.h>
#include <iostream>
using namespace std;
DWORD CALLBACK ThreadProc(LPVOID lpThreadParameter) {
char* szText = (char*)lpThreadParameter;
while (true) {
cout << szText << endl;
Sleep(1000);
}
return 0;
}
DWORD CALLBACK ThreadProc1(LPVOID lpThreadParameter) {
char* szText = (char*)lpThreadParameter;
while (true) {
cout << szText << endl;
Sleep(1000);
}
return 0;
}
int main() {
const char* pszText = "********";
DWORD nID = 0;
//线程立即执行
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)pszText, 0, &nID);
if (hThread == NULL) {
cout << "create thread failed" << GetLastError();
}
WaitForSingleObject(hThread, INFINITE);
const char* pszText1 = "--------";
DWORD nID1 = 0;
//线程挂起
HANDLE hThread1 = CreateThread(NULL, 0, ThreadProc1, (LPVOID)pszText1, 0, &nID1);
if (hThread1 == NULL) {
cout << "create thread failed" << GetLastError();
}
system("pause");
return 1;
}
六、线程同步
1.原子锁
(1).相关问题:多个线程对同一个数据进行原子操作,会产生结果丢失,比如执行++运算
(2).错误代码分析:当线程A执行g_value++时,如果线程切换时间正好是线程A将值保存到g_value之前线程B继续执行g_value++,那么当线程A再次被切换回来之后,会将原来线程A保存的值保存到g_value上,线程B进行的加法操作被覆盖。

(3).使用原子锁函数
InterlockedIncrement InterlockedDecrement InterlockedCompareExchange InterlockedExchange
原子锁的实现:直接对数据所在的内存操作,并且 在任何一个瞬间只能有一个线程访问
示例代码:
#include <Windows.h>
#include <iostream>
using namespace std;
long g_value = 0;
DWORD CALLBACK ThreadProc(LPVOID pParam) {
for (int i = 0; i < 100000000; i++) {
InterlockedIncrement(&g_value);
}
return 0;
}
DWORD CALLBACK ThreadProc1(LPVOID pParam) {
for (int i = 0; i < 100000000; i++) {
InterlockedIncrement(&g_value);
}
return 0;
}
int main() {
DWORD nID = 0;
HANDLE hThread[2];
hThread[0] = CreateThread(NULL, 0, ThreadProc, NULL, 0, &nID);
hThread[1] = CreateThread(NULL, 0, ThreadProc1, NULL, 0, &nID);
WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
cout << "wait over" << endl;
cout << g_value << endl;
return 1;
}
2.互斥锁
(1).相关的问题:多线程下代码或资源的共享使用
(2).创建互斥锁:
HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutextAttributes, //安全属性 BOOL bInitialOwner, //初始化的拥有者 TRUE(主线程拥有互斥)/FALSE(任何线程都不拥有互斥) LPCTSTR lpName //命名 ) 创建成功后返回互斥句柄
(3).等候互斥:WaittFor...互斥的等候遵循谁先等候谁先获取
(4).释放互斥锁:
BOOL ReleaseMutex( HANDLE hMutex //handle to mutex );
(5).关闭互斥句柄:CloseHandle
示例代码:
#include <Windows.h>
#include <iostream>
using namespace std;
HANDLE g_hMutex = 0;//互斥句柄
DWORD CALLBACK ThreadProc(LPVOID lpThreadParameter) {
char* szText = (char*)lpThreadParameter;
while (true) {
Sleep(1000);
//当任何线程拥有互斥的时候,则阻塞等待,反正则不阻塞继续执行,此时这个线程就拥有了互斥
//线程拥有互斥,则无信号阻塞等待,当所有线程都不拥有互斥,则是有信号,可以继续执行下去
WaitForSingleObject(g_hMutex, INFINITE);
for (int i = 0; i < strlen(szText); i++) {
printf("%c", szText[i]);
Sleep(125);
}
printf("\n");
ReleaseMutex(g_hMutex);
}
return 0;
}
DWORD CALLBACK ThreadProc1(LPVOID lpThreadParameter) {
char* szText = (char*)lpThreadParameter;
Sleep(1000);
while (true) {
WaitForSingleObject(g_hMutex, INFINITE);
for (int i = 0; i < strlen(szText); i++) {
printf("%c", szText[i]);
Sleep(125);
}
printf("\n");
ReleaseMutex(g_hMutex);
}
return 0;
}
int main() {
g_hMutex = CreateMutex(NULL, FALSE, NULL);
const char* pszText = "********";
DWORD nID = 0;
//线程立即执行
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)pszText, 0, &nID);
if (hThread == NULL) {
cout << "create thread failed" << GetLastError();
}
const char* pszText1 = "--------";
DWORD nID1 = 0;
//线程挂起
HANDLE hThread1 = CreateThread(NULL, 0, ThreadProc1, (LPVOID)pszText1, 0, &nID1);
if (hThread1 == NULL) {
cout << "create thread failed" << GetLastError();
}
getchar();
CloseHandle(g_hMutex);
return 1;
}
3.事件
(1).相关问题:线程之间的通知的问题
(2).创建事件:
HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, //安全属性 //由有信号变成无信号为复位,而由无信号变成有信号则为触发 BOOL bManualReset, //事件重置(复位)方式,TRUE手动,FALSE自动 BOOL bInitialSate, //事件初始状态,TRUE有信号 LPCTSTR lpName //事件名 ); 创建成功后返回事件句柄
(3).等候事件:WaitForSingleObject/WaitForMultipleObjects
(4).触发事件(将事件设置成有信号状态)
BOOL SetEvent(
HANDLE hEvent //handle to event
);
(5).复位事件(将事件设置成无信号状态)
BOOL ResetEvent(
HANDLE hEvent //handle to vent
);
(6).关闭事件:CloseHandle
示例代码:
#include <Windows.h>
#include <stdio.h>
HANDLE g_hEvent = NULL; //事件句柄
DWORD CALLBACK PrintProc(LPVOID lpThreadParameter) {
while (true) {
WaitForSingleObject(g_hEvent, INFINITE);
printf("**************************\n");
ResetEvent(g_hEvent);
}
return 1;
}
DWORD CALLBACK CtrlProc(LPVOID lpThreadParameter) {
while (true) {
Sleep(1000);
SetEvent(g_hEvent);
}
return 1;
}
int main() {
g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD nID = 0;
HANDLE hThread[2] = { 0 };
hThread[0] = CreateThread(NULL, 0, PrintProc, NULL, 0, &nID);
hThread[1] = CreateThread(NULL, 0, CtrlProc, NULL, 0, &nID);
WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
CloseHandle(g_hEvent);
return 1;
}
4.信号量
(1).相关的问题:类似于事件,解决通知的相关问题,但提供一个计数器,可以设置次数
(2).创建信号量:
HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, //安全属性 LONG lInitialCount, //初始化信号量数量 LONG lMaximumCount, //信号量的最大值 LPCTSTR lpName //命名 ); 创建成功后返回信号量句柄
(3).等候信号量:WaitFor...每等候通过一次,信号量的信号减1,直到为0阻塞
(4).给信号量指定计数值:
BOOL ReleaseSemaphore( HANDLE hSemaphore, //信号量句柄 LONG lReleaseCount, //释放数量 LPLONG lpPreviouseCount //释放前原来信号量的数量,可以为NULL );
(5).关闭句柄:CloseHandle
示例代码:
#include <Windows.h>
#include <stdio.h>
HANDLE g_hSema = NULL; //信号量句柄
DWORD CALLBACK SemaProc(LPVOID lpThreadParameter) {
while (true) {
WaitForSingleObject(g_hSema, INFINITE);
printf("******************\n");
}
return 0;
}
int main() {
g_hSema = CreateSemaphore(NULL, 3, 10, NULL);
DWORD nID = 0;
HANDLE hThread = CreateThread(NULL, 0, SemaProc, NULL, 0, &nID);
getchar();
ReleaseSemaphore(g_hSema, 5, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(g_hSema);
return 0;
}

浙公网安备 33010602011771号