C++多線程編程簡(jiǎn)單實(shí)例
C++本身并沒(méi)有提供任何多線程機(jī)制,但是在windows下,我們可以調(diào)用SDK win32 api來(lái)編寫多線程的程序,下面就此簡(jiǎn)單的講一下:
創(chuàng)建線程的函數(shù)
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId // thread identifier
);
在這里我們只用到了第三個(gè)和第四個(gè)參數(shù),第三個(gè)參數(shù)傳遞了一個(gè)函數(shù)的地址,也是我們要指定的新的線程,第四個(gè)參數(shù)是傳給新線程的參數(shù)指針。
eg1:
#include <iostream>
#include <windows.h>
using namespace std;
DWORD WINAPI Fun(LPVOID lpParamter)
{
while(1) { cout<<"Fun display!"<<endl; }
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
CloseHandle(hThread);
while(1) { cout<<"main display!"<<endl; }
return 0;
}
我們可以看到主線程(main函數(shù))和我們自己的線程(Fun函數(shù))是隨機(jī)地交替執(zhí)行的,但是兩個(gè)線程輸出太快,使我們很難看清楚,我們可以使用函數(shù)
VOID Sleep(
DWORD dwMilliseconds // sleep time
);
來(lái)暫停線程的執(zhí)行,dwMilliseconds表示千分之一秒,所以
Sleep(1000);
表示暫停1秒
eg2:
#include <iostream>
#include <windows.h>
using namespace std;
DWORD WINAPI Fun(LPVOID lpParamter)
{
while(1) { cout<<"Fun display!"<<endl; Sleep(1000);}
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
CloseHandle(hThread);
while(1) { cout<<"main display!"<<endl; Sleep(2000);}
return 0;
}
執(zhí)行上述代碼,這次我們可以清楚地看到在屏幕上交錯(cuò)地輸出Fun display!和main display!,我們發(fā)現(xiàn)這兩個(gè)函數(shù)確實(shí)是并發(fā)運(yùn)行的,細(xì)心的讀者可能會(huì)發(fā)現(xiàn)我們的程序是每當(dāng)Fun函數(shù)和main函數(shù)輸出內(nèi)容后就會(huì)輸出換行,但是我們看到的確是有的時(shí)候程序輸出換行了,有的時(shí)候確沒(méi)有輸出換行,甚至有的時(shí)候是輸出兩個(gè)換行。這是怎么回事?下面我們把程序改一下看看:
eg3:
#include <iostream>
#include <windows.h>
using namespace std;
DWORD WINAPI Fun(LPVOID lpParamter)
{
while(1) { cout<<"Fun display!\n"; Sleep(1000);}
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
CloseHandle(hThread);
while(1) { cout<<"main display!\n"; Sleep(2000);}
return 0;
}
我們?cè)俅芜\(yùn)行這個(gè)程序,我們發(fā)現(xiàn)這時(shí)候正如我們預(yù)期的,正確地輸出了我們想要輸出的內(nèi)容并且格式也是正確的。下面我就來(lái)講一下此前我們的程序?yàn)槭裁礇](méi)有正確的運(yùn)行。多線程的程序時(shí)并發(fā)地運(yùn)行的,多個(gè)線程之間如果公用了一些資源的話,我們并不能保證這些資源都能正確地被利用,因?yàn)檫@個(gè)時(shí)候資源并不是獨(dú)占的,舉個(gè)例子吧:
eg4:
加入有一個(gè)資源 int a = 3
有一個(gè)線程函數(shù) selfAdd() 該函數(shù)是使 a += a;
又有一個(gè)線程函數(shù) selfSub() 該函數(shù)是使a -= a;
我們假設(shè)上面兩個(gè)線程正在并發(fā)欲行,如果selfAdd在執(zhí)行的時(shí)候,我們的目的是想讓a編程6,但此時(shí)selfSub得到了運(yùn)行的機(jī)會(huì),所以a變成了0,等到selfAdd的到執(zhí)行的機(jī)會(huì)后,a += a ,但是此時(shí)a確是0,并沒(méi)有如我們所預(yù)期的那樣的到6,我們回到前面EG2,在這里,我們可以把屏幕看成是一個(gè)資源,這個(gè)資源被兩個(gè)線程所共用,加入當(dāng)Fun函數(shù)輸出了Fun display!后,將要輸出endl(也就是清空緩沖區(qū)并換行,在這里我們可以不用理解什么事緩沖區(qū)),但此時(shí)main函數(shù)確得到了運(yùn)行的機(jī)會(huì),此時(shí)Fun函數(shù)還沒(méi)有來(lái)得及輸出換行就把CPU讓給了main函數(shù),而這時(shí)main函數(shù)就直接在Fun display!后輸出main display!,至于為什么有的時(shí)候程序會(huì)連續(xù)輸出兩個(gè)換行,讀者可以采用同樣的分析方法來(lái)分析,在這里我就不多講了,留給讀者自己思考了。
那么為什么我們把eg2改成eg3就可以正確的運(yùn)行呢?原因在于,多個(gè)線程雖然是并發(fā)運(yùn)行的,但是有一些操作是必須一氣呵成的,不允許打斷的,所以我們看到eg2和eg3的運(yùn)行結(jié)果是不一樣的。
那么,是不是eg2的代碼我們就不可以讓它正確的運(yùn)行呢?答案當(dāng)然是否,下面我就來(lái)講一下怎樣才能讓eg2的代碼可以正確運(yùn)行。這涉及到多線程的同步問(wèn)題。對(duì)于一個(gè)資源被多個(gè)線程共用會(huì)導(dǎo)致程序的混亂,我們的解決方法是只允許一個(gè)線程擁有對(duì)共享資源的獨(dú)占,這樣就能夠解決上面的問(wèn)題了。
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD
BOOL bInitialOwner, // initial owner
LPCTSTR lpName // object name
);
該函數(shù)用于創(chuàng)造一個(gè)獨(dú)占資源,第一個(gè)參數(shù)我們沒(méi)有使用,可以設(shè)為NULL,第二個(gè)參數(shù)指定該資源初始是否歸屬創(chuàng)建它的進(jìn)程,第三個(gè)參數(shù)指定資源的名稱。
HANDLE hMutex = CreateMutex(NULL,TRUE,"screen");
這條語(yǔ)句創(chuàng)造了一個(gè)名為screen并且歸屬于創(chuàng)建它的進(jìn)程的資源
BOOL ReleaseMutex(
HANDLE hMutex // handle to mutex
);
該函數(shù)用于釋放一個(gè)獨(dú)占資源,進(jìn)程一旦釋放該資源,該資源就不再屬于它了,如果還要用到,需要重新申請(qǐng)得到該資源。申請(qǐng)資源的函數(shù)如下
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
第一個(gè)參數(shù)指定所申請(qǐng)的資源的句柄,第二個(gè)參數(shù)一般指定為INFINITE,表示如果沒(méi)有申請(qǐng)到資源就一直等待該資源,如果指定為0,表示一旦得不到資源就返回,也可以具體地指定等待多久才返回,單位是千分之一秒。好了,該到我們來(lái)解決eg2的問(wèn)題的時(shí)候了,我們可以把eg2做一些修改,如下
eg5:
#include <iostream>
#include <windows.h>
using namespace std;
HANDLE hMutex;
DWORD WINAPI Fun(LPVOID lpParamter)
{
while(1) {
WaitForSingleObject(hMutex, INFINITE);
cout<<"Fun display!"<<endl;
Sleep(1000);
ReleaseMutex(hMutex);
}
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
hMutex = CreateMutex(NULL, FALSE, "screen");
CloseHandle(hThread);
while(1) {
WaitForSingleObject(hMutex, INFINITE);
cout<<"main display!"<<endl;
Sleep(2000);
ReleaseMutex(hMutex);
}
return 0;
}
運(yùn)行代碼正如我們所預(yù)期的輸出的內(nèi)容。
以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。
上一篇:使用C++描繪心形
欄 目:C語(yǔ)言
下一篇:C語(yǔ)言中字符和字符串處理(ANSI字符和Unicode字符)
本文標(biāo)題:C++多線程編程簡(jiǎn)單實(shí)例
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3145.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10如何判斷一個(gè)數(shù)是否為2的冪次方?若是,并判斷出來(lái)是多少次方
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10如何判斷一個(gè)數(shù)是否為4的冪次方?若是,并判斷出來(lái)是多少次方
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實(shí)例總結(jié)