簡體   English   中英

多線程中的執行流程是什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM