編譯器優化對多線程數據同步的影響(volatile詳解實驗二)

首先,這裏沒有博主的傻逼!

由此可見(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

圖1-1 程序語句運行順序

但是,這樣主線程不是應該輸出 :

In main pthread: a=4, b=1, c=4             

(其實是沒輸出的,因爲有個 if 判斷,if 的作用是在彙編程序中,有利於小白博主定位程序彙編代碼,按照流程,a b c 的值應該如上。)

2.上辦法

僅僅需要在共享的全局變量加以volatie修飾!

volatile int a = 1;

 

3.打破砂鍋問到底

在C語言代碼,我們始終都找不到其中的問題所在!我們深入彙編中看看!

圖3-1 彙編程序對比圖
左(加入volatile修飾全局變量)

4.所以

我們在多線程共享的全局變量中,需要注意加以 volatile 修飾,去確保數據同步!

5.坑

其實,找到這個方法去做實驗並不容易,爲什麼?因爲編譯器已經很“智能”,甚至幫你優化的同時還解決了優化帶來的問題,比如如果將 程序中:

while(val--);         換成 sleep()   會發現上述問題不會出現

編譯器照顧的十分全局了,知道sleep()會使線程釋放CPU控制權,再次進來的時候會重新從內存中讀取全局變量!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章