示例考慮將有兩個執行緒 T1 和 T2
你怎麼發現它們?
如果多個執行緒可以訪問相同的變數/資源/記憶體位置,並且至少執行緒正在更改變數/資源/記憶體位置的值,則可能發生 Race Condition 。因為如果一個執行緒正在改變變數/資源/記憶體位置的值而另一個執行緒試圖讀取相同的值,那麼它將不會獲得更新的值。
注意 :如果所有執行緒只是讀取*變數/資源/記憶體位置,*則不會發生 Race Condition 。
示例:程式受 Race Race 影響
#include <stdio.h>
#include <pthread.h>
int x= 0;
void* fun(void* in)
{
int i;
for ( i = 0; i < 10000000; i++ )
{
x++;
}
}
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
pthread_create(&t1, NULL, fun, NULL);
pthread_create(&t2, NULL, fun, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Point 2 >> X is: %d\n", x);
return 0;
}
我螢幕上的輸出是:
Point 1 >> X is: 0
Point 2 >> X is: 9925047
你的輸出會有所不同。但肯定不會是 20,000,000。由於兩個執行緒執行相同的迴圈並具有全域性變數 int x;
for ( i = 0; i < 10000000; i++ )
{
x++;
}
所以 x
線上 Point 2 >> X is: 9925047
的最終值應該是 20,000,000。但事實並非如此。
在讀取 x 和寫回 x 之間的時間內,x 的狀態可以被另一個執行緒更改。
假設一個執行緒檢索 x 的值,但尚未儲存它。另一個執行緒也可以檢索相同的 x 值(因為還沒有執行緒改變它),然後它們都將相同的值(x + 1)儲存回 x!
例:
執行緒 1:讀取 x,值為 7
執行緒 1:將 x 加 1,值現為 8
執行緒 2:讀取 x,值為 7
執行緒 1:在 x 中儲存 8
執行緒 2:將 x 加 1,值現為 8
執行緒 2:在 x 中儲存 8
你怎麼處理它們?
通過在訪問共享資源或互斥的程式碼之前採用某種鎖定機制,可以避免競爭條件。
以下是修改後的程式:
示例:已解決競爭條件問題
#include <stdio.h>
#include <pthread.h>
int x= 0;
//Create mutex
pthread_mutex_t test_mutex;
void* fun(void* in)
{
int i;
for ( i = 0; i < 10000000; i++ )
{
//Lock mutex before going to change variable
pthread_mutex_lock(&test_mutex);
x++;
//Unlock mutex after changing the variable
pthread_mutex_unlock(&test_mutex);
}
}
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
//Initlize mutex
pthread_mutex_init(&test_mutex, NULL);
pthread_create(&t1, NULL, fun, NULL);
pthread_create(&t2, NULL, fun, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
//Destroy mutex after use
pthread_mutex_destroy(&test_mutex);
printf("Point 2 >> X is: %d\n", x);
return 0;
}
以下是輸出:
Point 1 >> X is: 0
Point 2 >> X is: 20000000
在這裡,答案每次都是 20,000,000。
注意 :修改後的程式沒有競爭條件錯誤,執行起來需要很長時間。因為 mutex
鎖定和解鎖有負擔。