C 拾遺 多執行緒 C語言多執行緒的引入

2021-06-28 16:33:14 字數 3602 閱讀 7749

c++拾遺--多執行緒:c語言多執行緒的引入

多執行緒是程式設計中的乙個重要內容。多核時代使多執行緒成為一種可能,顯然,一件事情多個人幹,效率一定會提公升。下面來看下c語言中是如何使用多執行緒的。

先來看乙個例項

#define _crt_secure_no_warnings

#include #include #include #include dword winapi run(void *p)

int main(void)

; handle handles[3];

for (int i = 0; i < sizeof(mess) / sizeof(*mess); i++)

waitformultipleobjects(3, handles, 1, infinite);

return 0;

}

執行

非同步彈出了三個視窗,並列印了各自的執行緒號。若是有沒看懂的地方,下面有詳細解釋:

1.handle是控制代碼,在windows中用控制代碼來標識物件。本質很簡單 typedef void * handle;

2.createthread()用來建立執行緒。原型

handle winapi createthread(

lpsecurity_attributes lpthreadattributes,    //核心物件的安全屬性

size_t dwstacksize,                          //執行緒棧大小

lpthread_start_routine lpstartaddress,       //執行緒函式位址

lpvoid lpparameter,                          //傳給執行緒函式的引數

dword dwcreationflags,                       //控制位

lpdword lpthreadid                           //獲取執行緒id

);引數解釋:

第乙個引數是執行緒核心物件的安全屬性,一般傳入

null

表示使用預設設定。

第二個引數是執行緒棧空間的大小。傳入

0表示使用預設大小(

1mb)。

第三個引數是新執行緒所執行的執行緒函式位址,多個執行緒可以使用同乙個函式位址。

第四個引數是傳給執行緒函式的引數。typedef void * lpvoid

第五個引數是用來控制線程的建立,0表示建立後立即執行。

第六個引數是傳出引數,用來獲得執行緒的id。顯然,傳入null,表示呼叫者並不想知道執行緒的id。

返回值:執行緒控制代碼

3.執行緒函式的宣告。#define winapi __stdcall  (vs2013)typedef unsigned long dword。其中,__stdcall是指c/cpp中函式的呼叫方式。主要有兩點:1.實參從右向左入棧。2.呼叫者負責清空引數棧。

4.執行緒等待函式

dword winapi waitformultipleobjects(

dword ncount,             //核心物件的個數

const handle *lphandles,  //控制代碼陣列的位址

bool bwaitall,            //是否等待所有

dword dwmilliseconds      //等待的最大時間,單位毫秒,infinite表示無限等待);

函式功能:讓執行緒進入等待轉態,直到條件觸發。核心物件在執行期間處於未觸發的狀態,直到執行結束。

5.執行緒函式型別是

typedef dword (winapi *pthread_start_routine)(lpvoid lpthreadparameter);

更簡潔的是

typedef unsigned long (__stdcall *pfun)(void*);

函式原型

uintptr_t __cdecl _beginthreadex(

void*                    _security,

unsigned                 _stacksize,

_beginthreadex_proc_type _startaddress,

void*                    _arglist,

unsigned                 _initflag,

unsigned*                _thrdaddr

);它的引數型別和createthread基本一致,只是執行緒函式型別稍有不同。執行緒函式型別是

typedef unsigned (__stdcall *_beginthreadex_proc_type)(void*);

createthread的呼叫過於複雜,下面我們玩兒個簡單的,我們用多個執行緒列印 hello world

#include #include #include #include void hello(void *p)

int main()

waitformultipleobjects(5, handles, 1, infinite);

getchar();

return 0;

}

執行

_beginthread的原型

uintptr_t _beginthread(

_beginthread_proc_type _startaddress,    //執行緒函式的位址

unsigned               _stacksize,       //執行緒棧的大小

void*                  _arglist          //執行緒函式的引數);

函式功能:使用指定執行緒函式建立執行緒,並返回執行緒控制代碼。

幾點解釋:

1.typedef unsigned int * uintptr_t;

2.typedef void(__cdecl *_beginthread_proc_type)(void*);  _beginthread_proc_type就是一函式指標型別,我們提供的執行緒函式應該如此設計:只有乙個引數,型別為void*,且返回值型別是void。

createthread和_beginthread的使用說明:

從函式引數可以看出,createthread用於對所建立的執行緒進行精細控制。在很多引數處於預設設定下,建議使用引數簡單的_beginthread。

兩者所需的執行緒函式型別不同。

使用多執行緒,就要先寫好執行緒函式,然後呼叫相關函式建立執行緒即可。由於_beginthread傳參簡單,一般情況下,使用_beginthread建立多執行緒。

多個子執行緒對同乙個全域性變數進行操作,容易引起執行緒衝突,也就是子執行緒的互斥問題。

主線程與子執行緒之間的同步問題。

後續文章,會對這兩個問題的解決進行**。

本專欄目錄

所有內容的目錄

多執行緒拾遺 例題

原題 利用多執行緒迴圈列印a b c 思路一 printa printb printc 三個方法,對this加鎖,根據乙個flag來控制列印物件。public class abcre system.out.print a flag b notifyall public synchronized vo...

多執行緒設計拾遺

1 synchronized不能繼承,父類的方法是synchronized,那麼其子類過載方法中就不會繼承 同步 2 構造兩個執行緒之間實時通訊的方法分幾步 1 建立乙個pipedwriter和乙個pipedreader和它們之間的管道 pipedreader in new pipedreader ...

C 拾遺 多執行緒 原子操作解決執行緒衝突

c 拾遺 多執行緒 原子操作解決執行緒衝突 在多執行緒中操作全域性變數一般都會引起執行緒衝突,為了解決執行緒衝突,引入原子操作。include include include include int g count 0 void count void p sleep 100 do some work...