簡單的多執行緒理解

2022-03-18 16:02:58 字數 3516 閱讀 1678

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 #include 

using

namespace

std;

dword winapi fun(lpvoid lpparamter)

}int

main()

return0;

}

我們可以看到主線程(main函式)和我們自己的執行緒(fun函式)是隨機地交替執行的,但是兩個執行緒輸出太快,使我們很難看清楚,我們可以使用函式

void sleep(

dword dwmilliseconds   // sleep time

來暫停執行緒的執行,dwmilliseconds表示千分之一秒,所以

sleep(1000);

表示暫停1秒

eg2:

#include #include 

using

namespace

std;

dword winapi fun(lpvoid lpparamter)

}int

main()

return0;

}

執行上述**,這次我們可以清楚地看到在螢幕上交錯地輸出fun display!和main display!,我們發現這兩個函式確實是併發執行的,細心的讀者可能會發現我們的程式是每當fun函式和main函式輸出內容後就會輸出換行,但是我們看到的確是有的時候程式輸出換行了,有的時候確沒有輸出換行,甚至有的時候是輸出兩個換行。這是怎麼回事?下面我們把程式改一下看看:

eg3:

#include #include 

using

namespace

std;

dword winapi fun(lpvoid lpparamter)

}int

main()

return0;

}

我們再次執行這個程式,我們發現這時候正如我們預期的,正確地輸出了我們想要輸出的內容並且格式也是正確的。下面我就來講一下此前我們的程式為什麼沒有正確的執行。多執行緒的程式時併發地執行的,多個執行緒之間如果公用了一些資源的話,我們並不能保證這些資源都能正確地被利用,因為這個時候資源並不是獨佔的,舉個例子吧:

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 #include 

using

namespace

std;

handle hmutex;

dword winapi fun(lpvoid lpparamter)

}int

main()

return0;

}

執行**正如我們所預期的輸出的內容。

簡單理解多執行緒ThredaLocal

要了解threadlocal,首先搞清楚threadlocal 是什麼?是用來解決什麼問題的?threadlocal 是執行緒的區域性變數,是每乙個執行緒所單獨持有的,其他執行緒不能對其進行訪問,通常是類中的 private static 字段,是對該字段初始值的乙個拷貝,它們希望將狀態與某乙個執行...

多執行緒 理解多執行緒(一)

程序 程序是cpu分配資源的基本單位 執行緒 執行緒是cpu排程的基本單位 資源分配給程序,所有執行緒共享該程序的資源 當執行緒數大於cpu的數量,會出現時間片的輪詢。cpu時間片是直接分配給執行緒的,執行緒拿到cpu時間片就能執行了 cpu時間片不是先分給程序然後再由程序分給程序下的執行緒的。所有...

多執行緒的理解

1.減少了建立和銷毀執行緒的次數,每個工作執行緒都可以被重複利用,可執行多個任務。2.可以根據系統的承受能力,調整執行緒池中工作線執行緒的數目,防止因為消耗過多的記憶體,而把伺服器累趴下 每個執行緒需要大約1mb記憶體,執行緒開的越多,消耗的記憶體也就越大,最後宕機 要配置乙個執行緒池是比較複雜的,...