問題背景:在工作中遇到過一個問題,就是在兩個線程同時調用同一個函數的時候,到底是應該在這個函數的內部什么處理上加上互斥。原因又是什么?
為了調查這個問題,我決定從以下三方面調查
1.線程中函數的調用
2.同一個進程中的兩個線程調用同一個處理函數
3.兩個不同進程中的兩個線程調用同一個處理函數
1.線程中函數的調用
每個進程都會有自己的虛擬地址空間,同一個進程中的每個線程都會在這個虛擬空間中,並被分配相應的資源。
線程中的函數實體是在內存中,而函數中的局部變量則會一次被push到棧中。
如果是A函數調用B函數,則會先將A函數的參數和局部變量push到隊列中,再將B函數的參數和局部變量push到隊列中
具體如下(參數是以從右到左壓入棧中,__stdcall與__cdecl調用約定都是這么處理的):
void fun(param1, param2,. param3....paramN)
{
value1;
value2;
...
valueN;
}
如果執行上面的函數在棧中會這樣變化
1:將fun函數的入力參數從右到左依次壓入到棧中。
2:將fun函數的指針壓入棧中
3:將ebp,ebx等寄存器入棧保存
4:在棧中依次為各個變量分配空間
執行后的處理:
1.釋放變量空間
2.彈出個寄存器
3.ret,彈出eip,返回主調方代碼
4.釋放參數空間
2.兩個線程調用同一個函數
兩個線程中的函數的局部變量由於是保存在不同的線程中,因此不需要進行互斥處理
3.兩個不同進程中的兩個線程調用同一個處理函數
同樣,兩個線程中的函數的局部變量由於是保存在不同的線程中,因此不需要進行互斥處理
結論:
因此需要互斥處理的,一般是函數中有
全局變量,有動態申請的空間,有靜態局部變量,有需要進程數據循環發送之類的操作需要進行互斥處理
