国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - C/C++ - C++中volatile關(guān)鍵字及常見(jiàn)的誤解總結(jié)

C++中volatile關(guān)鍵字及常見(jiàn)的誤解總結(jié)

2021-06-25 15:39趙宗晟 C/C++

這篇文章主要給大家介紹了關(guān)于C++中volatile關(guān)鍵字及常見(jiàn)的誤解的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

近期看到C++標(biāo)準(zhǔn)中對(duì)volatile關(guān)鍵字的定義,發(fā)現(xiàn)和java的volatile關(guān)鍵字完全不一樣,C++的volatile對(duì)并發(fā)編程基本沒(méi)有幫助。網(wǎng)上也看到很多關(guān)于volatile的誤解,于是決定寫(xiě)這篇文章詳細(xì)解釋一下volatile的作用到底是什么。

為什么用volatile?

C/C++ 中的 volatile 關(guān)鍵字和 const 對(duì)應(yīng),用來(lái)修飾變量,通常用于建立語(yǔ)言級(jí)別的 memory barrier。這是 BS 在 "The C++ Programming Language" 對(duì) volatile 修飾詞的說(shuō)明:

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 關(guān)鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統(tǒng)、硬件或者其它線程等。遇到這個(gè)關(guān)鍵字聲明的變量,編譯器對(duì)訪問(wèn)該變量的代碼就不再進(jìn)行優(yōu)化,從而可以提供對(duì)特殊地址的穩(wěn)定訪問(wèn)。聲明時(shí)語(yǔ)法:int volatile vInt; 當(dāng)要求使用 volatile 聲明的變量的值的時(shí)候,系統(tǒng)總是重新從它所在的內(nèi)存讀取數(shù)據(jù),即使它前面的指令剛剛從該處讀取過(guò)數(shù)據(jù)。而且讀取的數(shù)據(jù)立刻被保存。

編譯器對(duì)代碼的優(yōu)化

在講volatile關(guān)鍵字之前,先講一下編譯器的優(yōu)化。

?
1
2
3
4
5
int main() {
 int i = 0;
 i++;
 cout << "hello world" << endl;
}

按照代碼,這個(gè)程序會(huì)在內(nèi)存中預(yù)留int大小的空間,初始化這段內(nèi)存為0,然后這段內(nèi)存中的數(shù)據(jù)加1,最后輸出“hello world”到標(biāo)準(zhǔn)輸出中。但是根據(jù)這段代碼編譯出來(lái)的程序(加-O2選項(xiàng)),不會(huì)預(yù)留int大小的內(nèi)存空間,更不會(huì)對(duì)內(nèi)存中的數(shù)字加1。他只會(huì)輸出“hello world”到標(biāo)準(zhǔn)輸出中。

其實(shí)不難理解,這個(gè)是編譯器為了優(yōu)化代碼,修改了程序的邏輯。實(shí)際上C++標(biāo)準(zhǔn)是允許寫(xiě)出來(lái)的代碼和實(shí)際生成的程序不一致的。雖說(shuō)優(yōu)化代碼是件好事情,但是也不能讓編譯器任意修改程序邏輯,不然的話我們沒(méi)辦法寫(xiě)可靠的程序了。所以C++對(duì)這種邏輯的改寫(xiě)是有限制的,這個(gè)限制就是在編譯器修改邏輯后,程序?qū)ν饨绲腎O依舊是不變的。怎么理解呢?實(shí)際上我們可以把我們寫(xiě)出來(lái)的程序看做是一個(gè)黑匣子,如果按照相同的順序輸入相同的輸入,他就每次都會(huì)以同樣的順序給出同樣的輸出。這里的輸入輸出包括了標(biāo)準(zhǔn)輸入輸出、文件系統(tǒng)、網(wǎng)絡(luò)IO、甚至一些system call等等,所有程序外部的事物都包含在內(nèi)。所以對(duì)于程序使用者來(lái)說(shuō),只要兩個(gè)黑匣子的輸入輸出是完全一致的,那么這兩個(gè)黑匣子是一致的,所以編譯器可以在這個(gè)限制下任意改寫(xiě)程序的邏輯。

volatile關(guān)鍵字的作用

不知道有沒(méi)有注意到,剛剛提到輸入輸出的時(shí)候,并沒(méi)有提到內(nèi)存,事實(shí)上,程序?qū)ψ约簝?nèi)存的操作不屬于外部的輸入輸出。這也是為什么在上述例子中,編譯器可以去除對(duì)i變量的操作。但是這又會(huì)出現(xiàn)一個(gè)麻煩,有些時(shí)候操作系統(tǒng)會(huì)把一些硬件映射到內(nèi)存上,讓程序通過(guò)對(duì)內(nèi)存的操作來(lái)操作這個(gè)硬件,比如說(shuō)把磁盤(pán)空間映射到內(nèi)存中。那么對(duì)這部分內(nèi)存的操作實(shí)際上就屬于對(duì)程序外部的輸入輸出了。對(duì)這部分內(nèi)存的操作是不能隨便修改順序的,更不能忽略。這個(gè)時(shí)候volatile就可以派上用場(chǎng)了。按照C++標(biāo)準(zhǔn),對(duì)于glvalue的volatile變量進(jìn)行操作,與其他輸入輸出一樣,順序和內(nèi)容都是不能改變的。這個(gè)結(jié)果就像是把對(duì)volatile的操作看做程序外部的輸入輸出一樣。(glvalue是值類別的一種,簡(jiǎn)單說(shuō)就是內(nèi)存上分配有空間的對(duì)象,更詳細(xì)的請(qǐng)看我的另一篇文章。)

按照C++標(biāo)準(zhǔn),這是volatile唯一的功能,但是在一些編譯器(如,MSVC)中,volatile還有線程同步的功能,但這就是編譯器自己的拓展了,并不能跨平臺(tái)應(yīng)用。

對(duì)volatile常見(jiàn)的誤解

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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();
...

對(duì)volatile有誤解的人,或者對(duì)并發(fā)編程不了解的人可能會(huì)覺(jué)得這段邏輯沒(méi)什么問(wèn)題,可能會(huì)認(rèn)為volatile保證了,wait()對(duì)m_flag的讀取,notify()對(duì)m_flag的寫(xiě)入,所以Thread 1能夠正常醒來(lái)。實(shí)際上并不是,Thread 1可能永遠(yuǎn)看不到m_flag變成true。因?yàn)樵诙嗪薈PU中,每個(gè)CPU都有自己的緩存。緩存中存有一部分內(nèi)存中的數(shù)據(jù),CPU要對(duì)內(nèi)存讀取與存儲(chǔ)的時(shí)候都會(huì)先去操作緩存,而不會(huì)直接對(duì)內(nèi)存進(jìn)行操作。所以多個(gè)CPU“看到”的內(nèi)存中的數(shù)據(jù)是不一樣的,這個(gè)叫做內(nèi)存可見(jiàn)性問(wèn)題(memory visibility)。并發(fā)編程下,一個(gè)程序可以有多個(gè)線程在不同的CPU核中同時(shí)運(yùn)行,這個(gè)時(shí)候內(nèi)存可見(jiàn)性就會(huì)影響程序的正確性。放到例子中就是,Thread 2修改了m_flag對(duì)應(yīng)的內(nèi)存,但是Thread 1在其他CPU核上運(yùn)行,而兩個(gè)CPU緩存和內(nèi)存沒(méi)有做同步,導(dǎo)致Thread 1運(yùn)行的核上看到的一直都是舊的數(shù)據(jù),于是Thread 1永遠(yuǎn)都不能醒來(lái)。內(nèi)存可見(jiàn)性問(wèn)題不是多線程環(huán)境下會(huì)遇到的唯一的問(wèn)題,CPU的亂序執(zhí)行也會(huì)導(dǎo)致一些意想不到的事情發(fā)生,關(guān)于這點(diǎn)volatile能做的也是有限的。這些都是屬于并發(fā)編程的內(nèi)容,在此我就不多做展開(kāi),總之volatile關(guān)鍵字對(duì)并發(fā)編程基本是沒(méi)有幫助的。

那么用不了volatile,我們?cè)撛趺葱薷纳厦娴睦樱緾++11開(kāi)始有一個(gè)很好用的庫(kù),那就是atomic類模板,在<atomic>頭文件中,多個(gè)線程對(duì)atomic對(duì)象進(jìn)行訪問(wèn)是安全的。以下為修改后的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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模板重載了常用的運(yùn)算符,所以atomic<bool>使用起來(lái)和普通的bool變量差別不大。一些atomic的高級(jí)用法,由于要涉及到C++的內(nèi)存模型與并發(fā)編程,我就不在此展開(kāi)了,以后有時(shí)間再補(bǔ)上。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。

原文鏈接:https://www.cnblogs.com/zhao-zongsheng/p/9092520.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产高清在线精品一区二区三区 | 黑森林av凹凸导航 | 午夜影院在线观看 | 亚洲国产高清美女在线观看 | 亚洲天堂黄色 | 欧美一区二区三区在线看 | 免费一级在线视频 | 国变精品美女久久久久av爽 | 亚洲视频在线观看 | 黄色片网站 | 观看av| 欧美三级影院 | 亚洲男人天堂2023 | 国产黄色小视频 | 亚洲综合无码一区二区 | 97精品久久 | 国产中文久久 | 欧美精品成人一区二区三区四区 | 久久久久久久免费 | 亚洲一区二区美女 | 国产精品毛片a√一区 | 国产一区二区三区视频在线观看 | 久久精品免费 | 亚洲成人高清 | 可以看av的网站 | 国产精品久久国产精品 | 欧美黄色一区 | 久久久久久一区二区三区 | 亚洲日韩欧美一区二区在线 | 爱色av网站 | 精品久 | 久草福利| 二区三区在线 | 亚洲精品久久久一区二区三区 | 精品久久一二三区 | 亚洲一区 日韩精品 中文字幕 | 久久精品一区 | 成人在线观看h | 亚洲精品乱码久久久久久金桔影视 | 亚洲国产日韩欧美 | 成人免费网站 |