亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++中volatile關鍵字及常見的誤解總結

2020-05-23 13:26:41
字體:
來源:轉載
供稿:網友

前言

近期看到C++標準中對volatile關鍵字的定義,發現和java的volatile關鍵字完全不一樣,C++的volatile對并發編程基本沒有幫助。網上也看到很多關于volatile的誤解,于是決定寫這篇文章詳細解釋一下volatile的作用到底是什么。

為什么用volatile?

C/C++ 中的 volatile 關鍵字和 const 對應,用來修飾變量,通常用于建立語言級別的 memory barrier。這是 BS 在 "The C++ Programming Language" 對 volatile 修飾詞的說明:

A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided.

volatile 關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統、硬件或者其它線程等。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優化,從而可以提供對特殊地址的穩定訪問。聲明時語法:int volatile vInt; 當要求使用 volatile 聲明的變量的值的時候,系統總是重新從它所在的內存讀取數據,即使它前面的指令剛剛從該處讀取過數據。而且讀取的數據立刻被保存。

編譯器對代碼的優化

在講volatile關鍵字之前,先講一下編譯器的優化。

int main() { int i = 0; i++; cout << "hello world" << endl;}

按照代碼,這個程序會在內存中預留int大小的空間,初始化這段內存為0,然后這段內存中的數據加1,最后輸出“hello world”到標準輸出中。但是根據這段代碼編譯出來的程序(加-O2選項),不會預留int大小的內存空間,更不會對內存中的數字加1。他只會輸出“hello world”到標準輸出中。

其實不難理解,這個是編譯器為了優化代碼,修改了程序的邏輯。實際上C++標準是允許寫出來的代碼和實際生成的程序不一致的。雖說優化代碼是件好事情,但是也不能讓編譯器任意修改程序邏輯,不然的話我們沒辦法寫可靠的程序了。所以C++對這種邏輯的改寫是有限制的,這個限制就是在編譯器修改邏輯后,程序對外界的IO依舊是不變的。怎么理解呢?實際上我們可以把我們寫出來的程序看做是一個黑匣子,如果按照相同的順序輸入相同的輸入,他就每次都會以同樣的順序給出同樣的輸出。這里的輸入輸出包括了標準輸入輸出、文件系統、網絡IO、甚至一些system call等等,所有程序外部的事物都包含在內。所以對于程序使用者來說,只要兩個黑匣子的輸入輸出是完全一致的,那么這兩個黑匣子是一致的,所以編譯器可以在這個限制下任意改寫程序的邏輯。

volatile關鍵字的作用

不知道有沒有注意到,剛剛提到輸入輸出的時候,并沒有提到內存,事實上,程序對自己內存的操作不屬于外部的輸入輸出。這也是為什么在上述例子中,編譯器可以去除對i變量的操作。但是這又會出現一個麻煩,有些時候操作系統會把一些硬件映射到內存上,讓程序通過對內存的操作來操作這個硬件,比如說把磁盤空間映射到內存中。那么對這部分內存的操作實際上就屬于對程序外部的輸入輸出了。對這部分內存的操作是不能隨便修改順序的,更不能忽略。這個時候volatile就可以派上用場了。按照C++標準,對于glvalue的volatile變量進行操作,與其他輸入輸出一樣,順序和內容都是不能改變的。這個結果就像是把對volatile的操作看做程序外部的輸入輸出一樣。(glvalue是值類別的一種,簡單說就是內存上分配有空間的對象,更詳細的請看我的另一篇文章。)

按照C++標準,這是volatile唯一的功能,但是在一些編譯器(如,MSVC)中,volatile還有線程同步的功能,但這就是編譯器自己的拓展了,并不能跨平臺應用。

對volatile常見的誤解

實際上“volatile可以在線程間同步”也是比較常見的誤解。比如以下的例子:

class AObject{public: void wait() { m_flag = false; while (!m_flag) {  this_thread::sleep(1000ms); } } void notify() { m_flag = true; }private: volatile bool m_flag;};AObject obj;...// Thread 1...obj.wait();...// Thread 2...obj.notify();...

對volatile有誤解的人,或者對并發編程不了解的人可能會覺得這段邏輯沒什么問題,可能會認為volatile保證了,wait()對m_flag的讀取,notify()對m_flag的寫入,所以Thread 1能夠正常醒來。實際上并不是,Thread 1可能永遠看不到m_flag變成true。因為在多核CPU中,每個CPU都有自己的緩存。緩存中存有一部分內存中的數據,CPU要對內存讀取與存儲的時候都會先去操作緩存,而不會直接對內存進行操作。所以多個CPU“看到”的內存中的數據是不一樣的,這個叫做內存可見性問題(memory visibility)。并發編程下,一個程序可以有多個線程在不同的CPU核中同時運行,這個時候內存可見性就會影響程序的正確性。放到例子中就是,Thread 2修改了m_flag對應的內存,但是Thread 1在其他CPU核上運行,而兩個CPU緩存和內存沒有做同步,導致Thread 1運行的核上看到的一直都是舊的數據,于是Thread 1永遠都不能醒來。內存可見性問題不是多線程環境下會遇到的唯一的問題,CPU的亂序執行也會導致一些意想不到的事情發生,關于這點volatile能做的也是有限的。這些都是屬于并發編程的內容,在此我就不多做展開,總之volatile關鍵字對并發編程基本是沒有幫助的。

那么用不了volatile,我們該怎么修改上面的例子?C++11開始有一個很好用的庫,那就是atomic類模板,在<atomic>頭文件中,多個線程對atomic對象進行訪問是安全的。以下為修改后的代碼:

class AObject{public: void wait() { m_flag = false; while (!m_flag) {  this_thread::sleep(1000ms); } } void notify() { m_flag = true; }private: atomic<bool> m_flag;};

只要把“volatile bool”替換為“atomic<bool>”就可以。<atomic>頭文件也定義了若干常用的別名,例如“atomic<bool>”就可以替換為“atomic_bool”。atomic模板重載了常用的運算符,所以atomic<bool>使用起來和普通的bool變量差別不大。一些atomic的高級用法,由于要涉及到C++的內存模型與并發編程,我就不在此展開了,以后有時間再補上。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产自摸综合网| 国产精品美女无圣光视频| 欧美另类高清videos| 精品爽片免费看久久| 精品少妇一区二区30p| 久久久久久国产| 庆余年2免费日韩剧观看大牛| 亚洲精品久久久久久久久久久| 欧美中文在线观看| 欧美黑人性猛交| 九九热精品视频国产| 精品视频久久久久久久| 日韩在线精品一区| 亚洲色图校园春色| 精品久久久av| 欧美久久精品午夜青青大伊人| 色综合天天综合网国产成人网| 成人免费视频网址| 国产成人一区二区三区电影| 亚洲美女在线看| 日韩在线观看视频免费| 北条麻妃一区二区三区中文字幕| 国产午夜精品视频免费不卡69堂| 中文字幕九色91在线| 亚洲自拍偷拍网址| 欧美国产亚洲精品久久久8v| 亚洲高清av在线| 国产精品99久久久久久白浆小说| 色yeye香蕉凹凸一区二区av| 福利视频导航一区| 成人激情电影一区二区| 国产精品欧美一区二区| 亚洲人成77777在线观看网| 欧美精品在线网站| 久久亚洲国产精品成人av秋霞| 久久久亚洲精品视频| 92版电视剧仙鹤神针在线观看| 久久不射热爱视频精品| 麻豆国产va免费精品高清在线| 亚洲国产女人aaa毛片在线| 在线播放国产一区二区三区| 国产综合久久久久久| 久久久精品网站| 亚洲精品国精品久久99热一| 丝袜亚洲另类欧美重口| 久久久在线免费观看| 欧美亚洲在线播放| 精品人伦一区二区三区蜜桃网站| 国产精品一区二区三区久久| 午夜精品在线观看| 久久黄色av网站| 粗暴蹂躏中文一区二区三区| 久久免费国产视频| 国产偷国产偷亚洲清高网站| 欧美成人午夜视频| 亚洲欧美精品一区| 97国产精品视频人人做人人爱| 日韩一中文字幕| 久久久噜噜噜久久| 久久精品视频在线观看| 欧美成人午夜剧场免费观看| 亚洲欧美国内爽妇网| 国产91精品青草社区| 亚洲欧洲日产国产网站| 在线视频日韩精品| 精品久久久久久亚洲精品| 午夜精品久久久久久久久久久久久| 久色乳综合思思在线视频| 国产精品成熟老女人| 国产精品www色诱视频| 亚洲欧美成人网| 欧美激情精品久久久久久久变态| 国产成人自拍视频在线观看| 久久久久久免费精品| 欧美一级视频在线观看| 国产精品日本精品| 亚洲国产精品资源| 亚洲欧美精品中文字幕在线| 日韩av不卡在线| 亚洲天堂第一页| 国产精品777| 国产日韩亚洲欧美| 欧美激情亚洲自拍| 97在线精品国自产拍中文| 国产成人久久久| 欧美中文字幕视频| 国色天香2019中文字幕在线观看| 国产高清视频一区三区| 亚洲欧美视频在线| 九九视频这里只有精品| 色av吧综合网| 欧美国产第二页| 亚洲第一精品夜夜躁人人爽| 亚洲91精品在线| 91久久在线播放| 2019中文字幕在线免费观看| 成人h猎奇视频网站| 国精产品一区一区三区有限在线| 亚洲成人免费在线视频| 91精品视频在线| 精品久久久一区二区| 亚洲精品国产拍免费91在线| 日本精品在线视频| 91地址最新发布| 亚洲第一精品电影| 色综合色综合网色综合| 日韩av一卡二卡| 91精品久久久久久久久青青| 亚洲国产一区二区三区四区| 国产欧美日韩精品丝袜高跟鞋| 日韩在线精品一区| 日韩精品免费观看| 亚洲久久久久久久久久久| 亚洲欧洲午夜一线一品| 日本久久久久久久久| 国产成人精品免费久久久久| 97久久精品人搡人人玩| 成人高清视频观看www| 亚洲第一av网| 成人写真视频福利网| 日韩中文字幕视频在线| 欧美日韩激情视频8区| 91免费看视频.| 91免费看片在线| 91系列在线播放| 夜夜嗨av色综合久久久综合网| 国产女同一区二区| 亚洲一区二区三区乱码aⅴ| 亚洲福利视频二区| 色中色综合影院手机版在线观看| 久久久久久香蕉网| 日韩最新av在线| 欧美大全免费观看电视剧大泉洋| 性欧美激情精品| 国产精品高潮在线| 精品视频久久久久久久| 97在线视频国产| 欧美成人精品h版在线观看| 国产午夜精品全部视频在线播放| 欧美资源在线观看| 亚洲精品自拍视频| 成人午夜高潮视频| 亚洲欧美中文日韩v在线观看| 欧美日韩国产一区中文午夜| 国产精品96久久久久久又黄又硬| 精品久久久久久久久久国产| 欧美国产激情18| 91久久精品国产| 亚洲第一色在线| 久久成人亚洲精品| 自拍偷拍免费精品| 日韩黄在线观看| 欧美视频在线视频| 国产午夜精品一区理论片飘花| 尤物yw午夜国产精品视频明星| 国产综合在线看| 国语自产精品视频在线看一大j8| 91在线视频免费| 97久久精品人人澡人人爽缅北| 亚洲精品动漫100p| 亚洲国产欧美在线成人app| 亚洲精品国产精品久久清纯直播| 国产精品88a∨| 欧美综合激情网|