C++多線程編程簡略實例。本站提示廣大學習愛好者:(C++多線程編程簡略實例)文章只能為提供參考,不一定能成為您想要的結果。以下是C++多線程編程簡略實例正文
C++自己並沒有供給任何多線程機制,然則在windows下,我們可以挪用SDK win32 api來編寫多線程的法式,上面就此簡略的講一下:
創立線程的函數
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
);
在這裡我們只用到了第三個和第四個參數,第三個參數傳遞了一個函數的地址,也是我們要指定的新的線程,第四個參數是傳給新線程的參數指針。
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函數)和我們本身的線程(Fun函數)是隨機地瓜代履行的,然則兩個線程輸入太快,使我們很好看清晰,我們可使用函數
VOID Sleep(
DWORD dwMilliseconds // sleep time
);
來暫停線程的履行,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;
}
履行上述代碼,此次我們可以清晰地看到在屏幕上交織地輸入Fun display!和main display!,我們發明這兩個函數確切是並發運轉的,仔細的讀者能夠會發明我們的法式是每當Fun函數和main函數輸入內容後就會輸入換行,然則我們看到切實其實是有的時刻法式輸入換行了,有的時刻確沒有輸入換行,乃至有的時刻是輸入兩個換行。這是怎樣回事?上面我們把法式改一下看看:
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;
}
我們再次運轉這個法式,我們發明這時候候正如我們預期的,准確地輸入了我們想要輸入的內容而且格局也是准確的。上面我就來說一下此前我們的法式為何沒有准確的運轉。多線程的法式時並發地運轉的,多個線程之間假如公用了一些資本的話,我們其實不能包管這些資本都能准確地被應用,由於這個時刻資本其實不是獨有的,舉個例子吧:
eg4:
參加有一個資本 int a = 3
有一個線程函數 selfAdd() 該函數是使 a += a;
又有一個線程函數 selfSub() 該函數是使a -= a;
我們假定下面兩個線程正在並發欲行,假如selfAdd在履行的時刻,我們的目標是想讓a編程6,但此時selfSub獲得了運轉的機遇,所以a釀成了0,比及selfAdd的到履行的機遇後,a += a ,然則此時a確是0,並沒有如我們所預期的那樣的到6,我們回到後面EG2,在這裡,我們可以把屏幕算作是一個資本,這個資本被兩個線程所共用,參加當Fun函數輸入了Fun display!後,將要輸入endl(也就是清空緩沖區並換行,在這裡我們可以不消懂得甚麼事緩沖區),但此時main函數確獲得了運轉的機遇,此時Fun函數還沒有來得及輸入換行就把CPU讓給了main函數,而這時候main函數就直接在Fun display!後輸入main display!,至於為何有的時刻法式會持續輸入兩個換行,讀者可以采取異樣的剖析辦法來剖析,在這裡我就不多講了,留給讀者本身思慮了。
那末為何我們把eg2改成eg3便可以准確的運轉呢?緣由在於,多個線程固然是並發運轉的,然則有一些操作是必需趁熱打鐵的,不許可打斷的,所以我們看到eg2和eg3的運轉成果是紛歧樣的。
那末,是否是eg2的代碼我們就弗成以讓它准確的運轉呢?謎底固然能否,上面我就來說一下如何能力讓eg2的代碼可以准確運轉。這觸及到多線程的同步成績。關於一個資本被多個線程共用會招致法式的凌亂,我們的處理辦法是只許可一個線程具有對同享資本的獨有,如許就可以夠處理下面的成績了。
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD
BOOL bInitialOwner, // initial owner
LPCTSTR lpName // object name
);
該函數用於發明一個獨有資本,第一個參數我們沒有應用,可以設為NULL,第二個參數指定該資本初始能否歸屬創立它的過程,第三個參數指定資本的稱號。
HANDLE hMutex = CreateMutex(NULL,TRUE,"screen");
這條語句發明了一個名為screen而且歸屬於創立它的過程的資本
BOOL ReleaseMutex(
HANDLE hMutex // handle to mutex
);
該函數用於釋放一個獨有資本,過程一旦釋放該資本,該資本就不再屬於它了,假如還要用到,須要從新請求獲得該資本。請求資本的函數以下
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
第一個參數指定所請求的資本的句柄,第二個參數普通指定為INFINITE,表現假如沒有請求到資本就一向期待該資本,假如指定為0,表現一旦得不到資本就前往,也能夠詳細地指定期待多久才前往,單元是千分之一秒。好了,該到我們來處理eg2的成績的時刻了,我們可以把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;
}
運轉代碼正如我們所預期的輸入的內容。
以上所述就是本文的全體內容了,願望年夜家可以或許愛好。