[英]What is the flow of execution in Multi-threading?
我在多線程方面遇到了問題。 請考慮以下代碼:
#include<stdio.h>
#include<pthread.h>
void* functionA(void*);
void* functionB(void*);
int main()
{
pthread_t tid[2];
pthread_attr_t arg;
for(int i = 0; i<2; ++i)
{
pthread_attr_init(&arg);
if(i == 0)
{
int x = 0;
pthread_create(&tid[i], &arg, functionA, (void*)&x);
}
else if(i == 1)
{
int x = 6;
pthread_create(&tid[i], &arg, functionB, (void*)&x);
}
}
// wait for both threads to finish execution...
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
//.........................DEFINATIONS........................
void* functionA(void* x)
{
int Index = *((int*)x);
printf("First: %d\n",Index); //..................... LINE M
}
void* functionB(void* x)
{
int Index = *((int*)x);
printf("Second: %d\n",Index); //....................... LINE N
}
現在我相信functionA將首先開始執行,因為函數A的求助線程將首先在for循環中創建,所以根據我的輸出應該是:
First: 0 (from Line M)
Second: 6 (from Line N)
但實際輸出是,
Second: 6
First: 6
現在我很驚訝地看到這一點,我不知道發生了什么。 不僅secondFunction首先開始執行,而且兩個函數都顯示相同的值,即6,這對我來說沒有意義。 任何人都可以請你解釋一下這里發生了什么???? 提前致謝...
兩件事情
1)這里x變量范圍僅限於塊if。 所以在您的線程函數中,當您訪問該指針時,其范圍已經消失所以您正在訪問線程函數中的非法內存,這是錯誤的,它將創建未定義的行為。
回應你的一條評論
那么有沒有辦法代替變量,我可以直接發送一個常數,例如pthread_create(&tid [i],&arg,functionA,6)??
POSIX線程是一個C API。 C不提供像復制構造函數這樣的語言工具,因此無法按值復制任何對象。
你需要總是只通過指針傳遞一些東西。
2)執行線程的優先級是完全操作系統和調度程序依賴,你不能假設這些線程的序列。
你還想在線程之間進行一些同步,然后使用互斥,條件變量等。
您將指向短期局部變量的指針傳遞到線程中,一旦這些范圍退出就會導致未定義的行為。 可能兩個線程都看到x
的相同地址。
最明顯的解決方法是為變量使用更高的范圍,並且每個線程都有一個整數數組:
pthread_t tid[2];
pthread_attr_t arg;
int x[2] = { 0, 6 };
void * (*func[])(void *) = { functionA, functionB };
for(int i = 0; i < 2; ++i)
{
pthread_attr_init(&arg);
pthread_create(&tid[i], &arg, func[i], &x[i]);
}
// wait for both threads to finish execution...
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
這是有效的,因為x
數組將通過對pthread_join()
的調用。 也不需要int *
轉換指針, int *
自動轉換為C中的void *
。
關於線程開始順序的假設也是假的,沒有這樣的保證。
無法保證他們將以何種順序運行。 創建線程時,操作系統的調度程序將注冊新線程並在有時間時運行它。 基於系統上的優先級和其他hings,它可以按任何順序選擇它們,即中斷主線程並啟動其他線程,或運行主線程直到連接,然后啟動任何其他線程。
可能你正在測試多核系統。 那些甚至可能同時並行運行,但由於某種原因,一個或另一個可能更快(可能來自第二個的數據在緩存中,而第一個必須從內存中獲取數據?)
長話短說:沒有任何保證。
如果您需要特定訂單,您可以使用鎖(即互斥鎖)來強制執行同步,或者您可以設置優先級(請參閱setpriority())或強制實時調度(sched_setscheduler()),但您真的應該了解您的操作系統。
我相信functionA將首先開始執行,因為forA的forcourse線程將首先在for循環中創建
這種假設不正確,這取決於OS控制的線程調度。
如果要查看正確的輸出,請在main()
函數范圍內聲明兩個變量(在for
循環之前)
int x = 0;
int y = 6;
並且還要改變
pthread_create(&tid[i], &arg, functionA, (void*)&x);
pthread_create(&tid[i], &arg, functionB, (void*)&y);
通過這樣做,您至少可以獲得正確的輸出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.