多线程学习(一)----CreateThread
生活随笔
收集整理的這篇文章主要介紹了
多线程学习(一)----CreateThread
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
// tt.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#define WM_NIHAO? 1001
#define THREADNUM 3
/*
volatile 修飾符的作用是告訴編譯器無需對該變量作任何的優(yōu)化,即無需將它放到一個(gè)寄存器中,并且該值可被外部改變。
對于多線程引用的全局變量來說,volatile 是一個(gè)非常重要的修飾符。
*/
volatile int??????????? gInt=0;
//普通臨界區(qū)
static CRITICAL_SECTION cs;
//MFC臨界區(qū)
//CCriticalSection??????? ccs;
//使用原子操作的方法
volatile LONG aomic=100;
void fun(int tNum)
{
?? ?//printf("第%d線程已經(jīng)工作了\n",tNum);
?? ?if (1)
?? ?{
?? ??? ?//臨界區(qū)
?? ??? ?EnterCriticalSection(&cs);// 進(jìn)入臨界區(qū),其它線程則無法進(jìn)入
?? ??? ?//ccs.Lock();
?? ??? ?// 安全訪問該區(qū)域 ?
?? ??? ?gInt--;
?? ??? ?printf("第%d線程檢測到全局變量gInt的值是:%d\n",tNum,gInt);
?? ??? ?Sleep(0);//致使不使用臨界區(qū)肯定出錯(cuò)的方法
?? ??? ?gInt++;
?? ??? ?printf("第%d線程檢測到全局變量gInt的值是:%d\n",tNum,gInt);
?? ??? ?//ccs.Unlock();
?? ??? ?LeaveCriticalSection(&cs);? // 離開臨界區(qū),其它線程可以進(jìn)入
?? ??? ?//原子操作
?? ??? ?InterlockedIncrement(&aomic);
?? ??? ?InterlockedDecrement(&aomic);
?? ?}
?? ?MSG?? msg;? ?
?? ?//GetMessage 是 從調(diào)用線程的消息隊(duì)列里取得一個(gè)消息并將其放于指定的結(jié)構(gòu)。
?? ?//GetMessage不接收屬于其他線程或應(yīng)用程序的消息。獲取消息成功后,線程將從消息隊(duì)列中刪除該消息。函數(shù)會(huì)一直等待直到有消息到來才有返回值。
?? ?//返回值:如果函數(shù)取得WM_QUIT之外的其他消息,返回非零值。如果函數(shù)取得WM_QUIT消息,返回值是零。如果出現(xiàn)了錯(cuò)誤,返回值是-1。
?? ?while(1)
?? ?{? ?
?? ??? ?int tGM=::GetMessage(&msg,NULL,0,0);
?? ??? ?switch(msg.message)? ?
?? ??? ?{? ?
?? ??? ?case WM_NIHAO:? ?
?? ??? ??? ?printf("第%d線程接收到主線程的發(fā)過來的消息:%s\n",tNum,(char*)msg.wParam);
?? ??? ??? ??? ?break;
?? ??? ?default:
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?//不需要接收第二次消息
?? ??? ?if (tGM>0)
?? ??? ?{
?? ??? ??? ?break;
?? ??? ?}
?? ?}
?? ?printf("%d線程結(jié)束",tNum);
?? ?//該函數(shù)用于線程終結(jié)自身的執(zhí)行,主要在線程的執(zhí)行函數(shù)中被調(diào)用。其中參數(shù)dwExitCode用來設(shè)置線程的退出碼。
?? ?//ExitThread(1);
}
int _tmain(int argc, _TCHAR* argv[])
{
?? ?// 在進(jìn)入多線程環(huán)境之前,初始化臨界區(qū) ?
?? ?InitializeCriticalSection(&cs); ?
?? ?DWORD threadId[THREADNUM];
?? ?HANDLE hThread[THREADNUM];
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fun,(LPVOID)i,CREATE_SUSPENDED,&(threadId[i]));
?? ?}
?? ?while (getch()!='1')
?? ?{
?? ??? ?Sleep(100);
?? ?}
?? ?//試探線程讀取全局變量
?? ?gInt=100;
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?if (-1==ResumeThread(hThread[i]))
?? ??? ?{
?? ??? ??? ?printf("ResumeThread時(shí)候出錯(cuò)了\n");
?? ??? ??? ?return -1;
?? ??? ?}
?? ??? ?
?? ?}
?? ?//ResumeThread線程之后線程投入工作需要一定時(shí)間
?? ?Sleep(1000);
?? ?char buff[20]="ni hao ma?";
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?BOOL bPostMes=PostThreadMessage(threadId[i],WM_NIHAO,(WPARAM)buff,(LPARAM)strlen(buff));
?? ?}
?? ?//參數(shù)一:線程句柄
?? ?//參數(shù)二:等待時(shí)間(毫秒),IGNORE:不等,INFINITE:死等
?? ?//返回值: WAIT_OBJECT_0: 線程結(jié)束
?? ?//?? ??? ??? WAIT_TIMEOUT:超過等待時(shí)間,指定的對象處于無信號狀態(tài)
?? ?//?? ??? ??? WAIT_ABANDONED:WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll為TRUE,則返回值表明所有指定對象的狀態(tài)是觸發(fā)的,并且至少對象之一,是一個(gè)廢棄的互斥對象。
?? ?Sleep(1000);
?? ?//值得注意的是hThread數(shù)組的所有成員必須全部有效,有一個(gè)沒效的話,次函數(shù)就會(huì)執(zhí)行失敗
?? ?DWORD wm=WaitForMultipleObjects(THREADNUM,hThread,true,10000);
?? ?//若果第三個(gè)參數(shù)是true,則返回值代表所有線程的狀態(tài)
?? ?//若果第三個(gè)參數(shù)是false,則返回值代表那個(gè)有返回線程的狀態(tài)
?? ?switch (wm)
?? ?{
?? ?case WAIT_FAILED:
?? ??? ?printf("wm-->WAIT_FAILED\n");
?? ??? ?break;
?? ?case WAIT_TIMEOUT:
?? ??? ?printf("wm-->WAIT_TIMEOUT\n");
?? ??? ?break;
?? ?case WAIT_ABANDONED_0+0:
?? ?case WAIT_ABANDONED_0+1:
?? ?case WAIT_ABANDONED_0+2:
?? ??? ?printf("wm-->WAIT_ABANDONED_0\n");
?? ??? ?break;
?? ?case WAIT_OBJECT_0+0:
?? ?case WAIT_OBJECT_0+1:
?? ?case WAIT_OBJECT_0+2:
?? ??? ?printf("wm-->WAIT_OBJECT_0\n");
?? ??? ?break;
?? ?default:
?? ??? ?break;
?? ?}
?? ?//一般情況下,線程運(yùn)行結(jié)束之后,線程函數(shù)正常返回,但是應(yīng)用程序可以調(diào)用TerminateThread強(qiáng)行終止某一線程的執(zhí)行。
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?TerminateThread(hThread[i],0);
?? ?}
?? ?// 釋放臨界區(qū)資源,當(dāng)不再使用臨界區(qū)時(shí)調(diào)用該函數(shù) ?
?? ?DeleteCriticalSection(&cs); ?
?? ?return 0;
}
//同一進(jìn)程中的多個(gè)線程將共享該進(jìn)程中的全部系統(tǒng)資源,如虛擬地址空間、文件描述符和信號處理等,但是同一個(gè)進(jìn)程中的多個(gè)線程都有各自的調(diào)用棧、寄存器環(huán)境和線程本地存儲(chǔ)。
//線程都擁有自己的堆棧,臨界區(qū)等主要是控制訪問全局變量和成員變量
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#define WM_NIHAO? 1001
#define THREADNUM 3
/*
volatile 修飾符的作用是告訴編譯器無需對該變量作任何的優(yōu)化,即無需將它放到一個(gè)寄存器中,并且該值可被外部改變。
對于多線程引用的全局變量來說,volatile 是一個(gè)非常重要的修飾符。
*/
volatile int??????????? gInt=0;
//普通臨界區(qū)
static CRITICAL_SECTION cs;
//MFC臨界區(qū)
//CCriticalSection??????? ccs;
//使用原子操作的方法
volatile LONG aomic=100;
void fun(int tNum)
{
?? ?//printf("第%d線程已經(jīng)工作了\n",tNum);
?? ?if (1)
?? ?{
?? ??? ?//臨界區(qū)
?? ??? ?EnterCriticalSection(&cs);// 進(jìn)入臨界區(qū),其它線程則無法進(jìn)入
?? ??? ?//ccs.Lock();
?? ??? ?// 安全訪問該區(qū)域 ?
?? ??? ?gInt--;
?? ??? ?printf("第%d線程檢測到全局變量gInt的值是:%d\n",tNum,gInt);
?? ??? ?Sleep(0);//致使不使用臨界區(qū)肯定出錯(cuò)的方法
?? ??? ?gInt++;
?? ??? ?printf("第%d線程檢測到全局變量gInt的值是:%d\n",tNum,gInt);
?? ??? ?//ccs.Unlock();
?? ??? ?LeaveCriticalSection(&cs);? // 離開臨界區(qū),其它線程可以進(jìn)入
?? ??? ?//原子操作
?? ??? ?InterlockedIncrement(&aomic);
?? ??? ?InterlockedDecrement(&aomic);
?? ?}
?? ?MSG?? msg;? ?
?? ?//GetMessage 是 從調(diào)用線程的消息隊(duì)列里取得一個(gè)消息并將其放于指定的結(jié)構(gòu)。
?? ?//GetMessage不接收屬于其他線程或應(yīng)用程序的消息。獲取消息成功后,線程將從消息隊(duì)列中刪除該消息。函數(shù)會(huì)一直等待直到有消息到來才有返回值。
?? ?//返回值:如果函數(shù)取得WM_QUIT之外的其他消息,返回非零值。如果函數(shù)取得WM_QUIT消息,返回值是零。如果出現(xiàn)了錯(cuò)誤,返回值是-1。
?? ?while(1)
?? ?{? ?
?? ??? ?int tGM=::GetMessage(&msg,NULL,0,0);
?? ??? ?switch(msg.message)? ?
?? ??? ?{? ?
?? ??? ?case WM_NIHAO:? ?
?? ??? ??? ?printf("第%d線程接收到主線程的發(fā)過來的消息:%s\n",tNum,(char*)msg.wParam);
?? ??? ??? ??? ?break;
?? ??? ?default:
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?//不需要接收第二次消息
?? ??? ?if (tGM>0)
?? ??? ?{
?? ??? ??? ?break;
?? ??? ?}
?? ?}
?? ?printf("%d線程結(jié)束",tNum);
?? ?//該函數(shù)用于線程終結(jié)自身的執(zhí)行,主要在線程的執(zhí)行函數(shù)中被調(diào)用。其中參數(shù)dwExitCode用來設(shè)置線程的退出碼。
?? ?//ExitThread(1);
}
int _tmain(int argc, _TCHAR* argv[])
{
?? ?// 在進(jìn)入多線程環(huán)境之前,初始化臨界區(qū) ?
?? ?InitializeCriticalSection(&cs); ?
?? ?DWORD threadId[THREADNUM];
?? ?HANDLE hThread[THREADNUM];
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fun,(LPVOID)i,CREATE_SUSPENDED,&(threadId[i]));
?? ?}
?? ?while (getch()!='1')
?? ?{
?? ??? ?Sleep(100);
?? ?}
?? ?//試探線程讀取全局變量
?? ?gInt=100;
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?if (-1==ResumeThread(hThread[i]))
?? ??? ?{
?? ??? ??? ?printf("ResumeThread時(shí)候出錯(cuò)了\n");
?? ??? ??? ?return -1;
?? ??? ?}
?? ??? ?
?? ?}
?? ?//ResumeThread線程之后線程投入工作需要一定時(shí)間
?? ?Sleep(1000);
?? ?char buff[20]="ni hao ma?";
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?BOOL bPostMes=PostThreadMessage(threadId[i],WM_NIHAO,(WPARAM)buff,(LPARAM)strlen(buff));
?? ?}
?? ?//參數(shù)一:線程句柄
?? ?//參數(shù)二:等待時(shí)間(毫秒),IGNORE:不等,INFINITE:死等
?? ?//返回值: WAIT_OBJECT_0: 線程結(jié)束
?? ?//?? ??? ??? WAIT_TIMEOUT:超過等待時(shí)間,指定的對象處于無信號狀態(tài)
?? ?//?? ??? ??? WAIT_ABANDONED:WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll為TRUE,則返回值表明所有指定對象的狀態(tài)是觸發(fā)的,并且至少對象之一,是一個(gè)廢棄的互斥對象。
?? ?//???????? WAIT_FAILED:出現(xiàn)錯(cuò)誤,一般是線程句柄錯(cuò)誤
??? //WaitForSingleObject函數(shù),此函數(shù)的作用是監(jiān)視hHandle的狀態(tài),當(dāng)監(jiān)視的句柄為有信號狀態(tài)時(shí),即此對象為空閑狀態(tài)時(shí),此函數(shù)返回,才能執(zhí)行其后的代碼。
?? ?//WaitForSingleObject(hThread,INFINITE);?? ?Sleep(1000);
?? ?//值得注意的是hThread數(shù)組的所有成員必須全部有效,有一個(gè)沒效的話,次函數(shù)就會(huì)執(zhí)行失敗
?? ?DWORD wm=WaitForMultipleObjects(THREADNUM,hThread,true,10000);
?? ?//若果第三個(gè)參數(shù)是true,則返回值代表所有線程的狀態(tài)
?? ?//若果第三個(gè)參數(shù)是false,則返回值代表那個(gè)有返回線程的狀態(tài)
?? ?switch (wm)
?? ?{
?? ?case WAIT_FAILED:
?? ??? ?printf("wm-->WAIT_FAILED\n");
?? ??? ?break;
?? ?case WAIT_TIMEOUT:
?? ??? ?printf("wm-->WAIT_TIMEOUT\n");
?? ??? ?break;
?? ?case WAIT_ABANDONED_0+0:
?? ?case WAIT_ABANDONED_0+1:
?? ?case WAIT_ABANDONED_0+2:
?? ??? ?printf("wm-->WAIT_ABANDONED_0\n");
?? ??? ?break;
?? ?case WAIT_OBJECT_0+0:
?? ?case WAIT_OBJECT_0+1:
?? ?case WAIT_OBJECT_0+2:
?? ??? ?printf("wm-->WAIT_OBJECT_0\n");
?? ??? ?break;
?? ?default:
?? ??? ?break;
?? ?}
?? ?//一般情況下,線程運(yùn)行結(jié)束之后,線程函數(shù)正常返回,但是應(yīng)用程序可以調(diào)用TerminateThread強(qiáng)行終止某一線程的執(zhí)行。
?? ?for (int i=0;i<THREADNUM;i++)
?? ?{
?? ??? ?TerminateThread(hThread[i],0);
?? ?}
?? ?// 釋放臨界區(qū)資源,當(dāng)不再使用臨界區(qū)時(shí)調(diào)用該函數(shù) ?
?? ?DeleteCriticalSection(&cs); ?
?? ?return 0;
}
總結(jié)
以上是生活随笔為你收集整理的多线程学习(一)----CreateThread的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不错的博客
- 下一篇: API---有意思的API