支援多執行緒可謂是c++語言最大的變化之一.
此前,c++只能利用作業系統的功能(unix族系統使用pthreads庫),或是例如openmp和mpi這些**庫,來實現多核計算的目標.
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
);在這裡我們只用到了第三個和第四個引數,第三個引數傳遞了乙個函式的位址,也是我們要指定的新的執行緒。第四個引數是傳給新執行緒的引數指標
example1:
#include
#include
using
namespace
std;
dword
winapi
fun(lpvoid
lpparamter)
}int
main()
return0;}
我們可以看到主線程(main函式)和我們自己的執行緒(fun函式)是隨機地交替執行的.
但是兩個執行緒輸出太快,使我們很難看清楚,我們可以使用函式
來暫停執行緒的執行,dwmilliseconds表示千分之一秒,所以
sleep(1000);
表示暫停1秒
void
sleep(
dword
dwmilliseconds
// sleep time
);example2:
#include
#include
using
namespace
std;
dword
winapi
fun(lpvoid
lpparamter)
}int
main()
return0;}
執行上述**,這次我們可以清楚地看到在螢幕上交錯地輸出fun display!和main display!
我們發現這兩個函式確實是併發執行的,細心的讀者可能會發現我們的程式是每當fun函式和main函式輸出內容後就會輸出換行,
但是我們看到的確是有的時候程式輸出換行了,有的時候確沒有輸出換行,甚至有的時候是輸出兩個換行.
這是怎麼回事?下面我們把程式改一下看看:
example3:
#include
#include
using
namespace
std;
dword
winapi
fun(lpvoid
lpparamter)
}int
main()
return0;}
我們再次執行這個程式,我們發現這時候正如我們預期的,正確地輸出了我們想要輸出的內容並且格式也是正確的.
下面我就來講一下此前我們的程式為什麼沒有正確的執行.
多執行緒的程式時併發地執行的,多個執行緒之間如果公用了一些資源的話,我們並不能保證這些資源都能正確地被利用,因為這個時候資源並不是獨佔的,舉個例子吧:
example4:
加入有乙個資源 int a = 3
有乙個執行緒函式 selfadd() 該函式是使a = a+a
又有乙個執行緒函式 selfsub() 該函式是使a = a-a
我們假設上面兩個執行緒正在併發欲行,如果selfadd在執行的時候,我們的目的是想讓a程式設計6,但此時selfsub得到了執行的機會,所以a變成了0,
等到selfadd的到執行的機會後,a = a+a ,但是此時a確是0,並沒有如我們所預期的那樣的到6,
我們回到前面example2,在這裡,我們可以把螢幕看成是乙個資源,這個資源被兩個執行緒所共用,
加入當fun函式輸出了fun display!後,將要輸出endl(也就是清空緩衝區並換行,在這裡我們可以不用理解什麼事緩衝區),
但此時main函式確得到了執行的機會,此時fun函式還沒有來得及輸出換行就把cpu讓給了main函式,
而這時main函式就直接在fun display!後輸出main display!,至於為什麼有的時候程式會連續輸出兩個換行,
讀者可以採用同樣的分析方法來分析,在這裡我就不多講了,留給讀者自己思考了.
那麼為什麼我們把example2改成example3就可以正確的執行呢?原因在於,多個執行緒雖然是併發執行的,
但是有一些操作是必須一氣呵成的,不允許打斷的,所以我們看到example2和example3的執行結果是不一樣的.
那麼,是不是example2的**我們就不可以讓它正確的執行呢?
答案當然是否,下面我就來講一下怎樣才能讓example2的**可以正確執行.
這涉及到多執行緒的同步問題。對於乙個資源被多個執行緒共用會導致程式的混亂,我們的解決方法是只允許乙個執行緒擁有對共享資源的獨佔,這樣就能夠解決上面的問題了.
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,表示一旦得不到資源就返回,也可以具體地指定等待多久才返回,單位是千分之一秒。
現在我們來解決example2的問題,我們可以把example2做一些修改:
#include
#include
using
namespace
std;
handle
hmutex;
dword
winapi
fun(lpvoid
lpparamter)
}int
main()
return0;}
這樣即可解決問題.
C 多執行緒的實現
首先,上個多執行緒的概念。通過單獨的執行緒來執行某個任務,乙個多執行緒程式可以執行多個任務,而且這些執行緒都是並行執行,同時執行多個執行緒的能力稱為多執行緒。在c 裡面,net framework為我們提供了多執行緒的實現。微軟的msdn文件,也給出了例項。見 msdn thread類說明 下面上一...
C 實現多執行緒
include include include std mutex display mutex 使用互斥鎖 void foo int i void multithread for int i 0 i 4 i std thread thread foo,i thread.detach 執行緒資源 分離...
c 實現多執行緒同步
執行緒同步是指同一程序中的多個執行緒互相協調工作從而達到一致性。之所以需要執行緒同步,是因為多個執行緒同時對乙個資料物件進行修改操作時,可能會對資料造成破壞,下面是多個執行緒同時修改同一資料造成破壞的例子 1 include 2 include 3 4void fun 1 unsigned int ...