首先,這裏沒有博主的傻逼!
由此可見(C語言volatile關鍵字詳解),編譯器優化會對多線程數據同步有影響,我們深入程序輸出以及彙編程序去探討爲什麼會產生影響!並解決問題
1.上代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int a = 1;
void *child_pth_fun(void *arg);
int main(){
int b, c;
volatile int val = 10000000;
//創建子線程
pthread_t child_pth_id;
pthread_create(&child_pth_id, NULL, child_pth_fun, NULL);
b = a;
//模擬一段很長的程序段,消耗主線程時間片,以便系統調度子線程
while(val--);
c = a;
if(c == b)
printf("In main pthread: a=%d, b=%d, c=%d\n", a, b, a);
pthread_join(child_pth_id, NULL);
return 0;
}
void *child_pth_fun(void *arg){
//子線程修改共享的全局變量
a = 4;
printf("In child pthread: a=%d\n", a);
}
編譯命令:arm-linux-gcc -O3 -o pthread pthread.c
(使用gcc編譯器也可以,但是博主只會看一點點ARM彙編,後面要分析彙編,莫得辦法 - _ - ! )
程序輸出:
In child pthread: a=4
In main pthread: a=1, b=1, c=1
但是,這樣主線程不是應該輸出 :
In main pthread: a=4, b=1, c=4
(其實是沒輸出的,因爲有個 if 判斷,if 的作用是在彙編程序中,有利於小白博主定位程序彙編代碼,按照流程,a b c 的值應該如上。)
2.上辦法
僅僅需要在共享的全局變量加以volatie修飾!
volatile int a = 1;
3.打破砂鍋問到底
在C語言代碼,我們始終都找不到其中的問題所在!我們深入彙編中看看!
4.所以
我們在多線程共享的全局變量中,需要注意加以 volatile 修飾,去確保數據同步!
5.坑
其實,找到這個方法去做實驗並不容易,爲什麼?因爲編譯器已經很“智能”,甚至幫你優化的同時還解決了優化帶來的問題,比如如果將 程序中:
while(val--); 換成 sleep() 會發現上述問題不會出現
編譯器照顧的十分全局了,知道sleep()會使線程釋放CPU控制權,再次進來的時候會重新從內存中讀取全局變量!