我撰寫了一個簡單的 c 程式,使每個執行緒的索引乘以 1000000 并將其添加到 sum 中,我創建了 5 個執行緒,因此邏輯答案是 (0 1 2 3 4)*1000000,即 10000000,但它拋出14000000 代替。有人可以幫助我理解這一點嗎?
#include<pthread.h>
#include<stdio.h>
typedef struct argument {
int index;
int sum;
} arg;
void *fonction(void *arg0) {
((arg *) arg0) -> sum = ((arg *) arg0) -> index * 1000000;
}
int main() {
pthread_t thread[5];
int order[5];
arg a;
for (int i = 0; i < 5; i )
order[i] = i;
a.sum = 0;
for (int i = 0; i < 5; i ) {
a.index = order[i];
pthread_create(&thread[i], NULL, fonction, &a);
}
for (int i = 0; i < 5; i )
pthread_join(thread[i], NULL);
printf("%d\n", a.sum);
return 0;
}
uj5u.com熱心網友回復:
它是 140.. 因為行為是未定義的。結果會因不同的機器和其他環境因素而有所不同。未定義的行為是由于所有執行緒訪問同一個物件(見&a給每個執行緒)而導致的,該物件在第一個執行緒創建后被修改。
當每個執行緒運行時,它訪問相同的物件
index(作為訪問同一物件 (&a)的成員的一部分)。因此,執行緒將看到 [0,1,2,3,4] 的假設是不正確的:多個執行緒在運行時可能會看到相同的值index(例如 [0,2,4,4,4] 1)。這取決于回圈創建執行緒的調度,因為它也會修改共享物件。當每個執行緒更新時,
sum它必須讀取和寫入相同的共享記憶體。這本質上容易出現競爭條件和不可靠的結果。例如,它可能缺乏記憶體可見性(執行緒 X 沒有看到從執行緒 Y 更新的值),或者可能是讀取和寫入之間的執行緒調度沖突(執行緒 X 讀取、執行緒 Y 讀取、執行緒 X 寫入、執行緒Y寫)等。
如果為每個執行緒創建一個新的 arg 物件,則可以避免這兩個問題。雖然總和問題可以通過適當的鎖定來解決,但索引問題只能通過不共享作為執行緒輸入給出的物件來解決。
// create 5 arg objects, one for each thread
arg a[5];
for (..) {
a[i].index = i;
// give DIFFERENT object to each thread
pthread_create(.., &a[i]);
}
// after all threads complete
int sum = 0;
for (..) {
sum = a[i].result;
}
1即使假設當前執行 wrt 中沒有競爭條件。的用法sum,不同執行緒的序列看到index值為 [0,2,4,4,4],其總和為 14,可能如下所示:
- a.index <- 0 ; 創建執行緒A
- 執行緒 A 讀取 a.index (0)
- a.index <- 1 ; 創建執行緒B
- a.index <- 2 ; 創建執行緒 C
- 執行緒 B 讀取 a.index (2)
- a.index <- 3 ; 創建執行緒 D
- a.index <- 4 ; 創建執行緒 E
- 執行緒 D 讀取 a.index (4)
- 執行緒 C 讀取 a.index (4)
- 執行緒 E 讀取 a.index (4)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/373379.html
上一篇:C程式生成兩個行程樹而不是一個
下一篇:根據第二行對二維陣列進行排序
