黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

Java面向?qū)ο?/div>
Java異常
Java數(shù)組
Java常用類
Java集合
Java IO流
Java線程
Java反射
Socket編程
Java注解開發(fā)
Java GoF設(shè)計(jì)模式
HashMap
Java內(nèi)存模型
Java線性表

Java并發(fā)編程

原子性

原子性:即一個(gè)操作或者多個(gè)操作 要么全部執(zhí)行并且執(zhí)行的過程不會被任何因素打斷,要么就都不執(zhí)行。

一個(gè)很經(jīng)典的例子就是銀行賬戶轉(zhuǎn)賬問題:

比如從賬戶A向賬戶B轉(zhuǎn)1000元,那么必然包括2個(gè)操作:從賬戶A減去1000元,往賬戶B加上1000元。

試想一下,如果這2個(gè)操作不具備原子性,會造成什么樣的后果。假如從賬戶A減去1000元之后,操作突然中止。然后又從B取出了500元,取出500元之后,再執(zhí)行 往賬戶B加上1000元 的操作。這樣就會導(dǎo)致賬戶A雖然減去了1000元,但是賬戶B沒有收到這個(gè)轉(zhuǎn)過來的1000元。

所以這2個(gè)操作必須要具備原子性才能保證不出現(xiàn)一些意外的問題。

同樣地反映到并發(fā)編程中會出現(xiàn)什么結(jié)果呢?

舉個(gè)最簡單的例子,大家想一下假如為一個(gè)32位的變量賦值過程不具備原子性的話,會發(fā)生什么后果?

i = 9;

假若一個(gè)線程執(zhí)行到這個(gè)語句時(shí),我暫且假設(shè)為一個(gè)32位的變量賦值包括兩個(gè)過程:為低16位賦值,為高16位賦值。

那么就可能發(fā)生一種情況:當(dāng)將低16位數(shù)值寫入之后,突然被中斷,而此時(shí)又有一個(gè)線程去讀取i的值,那么讀取到的就是錯(cuò)誤的數(shù)據(jù)。

可見性

可見性是指當(dāng)多個(gè)線程訪問同一個(gè)變量時(shí),一個(gè)線程修改了這個(gè)變量的值,其他線程能夠立即看得到修改的值。

舉個(gè)簡單的例子,看下面這段代碼:  

//線程1執(zhí)行的代碼
int i = 0;
i = 10;
//線程2執(zhí)行的代碼
j = i;

假若執(zhí)行線程1的是CPU1,執(zhí)行線程2的是CPU2。由上面的分析可知,當(dāng)線程1執(zhí)行 i =10這句時(shí),會先把i的初始值加載到CPU1的高速緩存中,然后賦值為10,那么在CPU1的高速緩存當(dāng)中i的值變?yōu)?0了,卻沒有立即寫入到主存當(dāng)中。

此時(shí)線程2執(zhí)行 j = i,它會先去主存讀取i的值并加載到CPU2的緩存當(dāng)中,注意此時(shí)內(nèi)存當(dāng)中i的值還是0,那么就會使得j的值為0,而不是10。

這就是可見性問題,線程1對變量i修改了之后,線程2沒有立即看到線程1修改的值。

有序性

有序性:即程序執(zhí)行的順序按照代碼的先后順序執(zhí)行。舉個(gè)簡單的例子,看下面這段代碼:

int i = 0;              
boolean flag = false;
i = 1;                //語句1  
flag = true;          //語句2

上面代碼定義了一個(gè)int型變量,定義了一個(gè)boolean類型變量,然后分別對兩個(gè)變量進(jìn)行賦值操作。從代碼順序上看,語句1是在語句2前面的,那么JVM在真正執(zhí)行這段代碼的時(shí)候會保證語句1一定會在語句2前面執(zhí)行嗎?不一定,為什么呢?這里可能會發(fā)生指令重排序(Instruction Reorder)。

下面解釋一下什么是指令重排序,一般來說,處理器為了提高程序運(yùn)行效率,可能會對輸入代碼進(jìn)行優(yōu)化,它不保證程序中各個(gè)語句的執(zhí)行先后順序同代碼中的順序一致,但是它會保證程序最終執(zhí)行結(jié)果和代碼順序執(zhí)行的結(jié)果是一致的。

比如上面的代碼中,語句1和語句2誰先執(zhí)行對最終的程序結(jié)果并沒有影響,那么就有可能在執(zhí)行過程中,語句2先執(zhí)行而語句1后執(zhí)行。

但是要注意,雖然處理器會對指令進(jìn)行重排序,但是它會保證程序最終結(jié)果會和代碼順序執(zhí)行結(jié)果相同,那么它靠什么保證的呢?再看下面一個(gè)例子:

上面代碼定義了一個(gè)int型變量,定義了一個(gè)boolean類型變量,然后分別對兩個(gè)變量進(jìn)行賦值操作。從代碼順序上看,語句1是在語句2前面的,那么JVM在真正執(zhí)行這段代碼的時(shí)候會保證語句1一定會在語句2前面執(zhí)行嗎?不一定,為什么呢?這里可能會發(fā)生指令重排序(Instruction Reorder)。

下面解釋一下什么是指令重排序,一般來說,處理器為了提高程序運(yùn)行效率,可能會對輸入代碼進(jìn)行優(yōu)化,它不保證程序中各個(gè)語句的執(zhí)行先后順序同代碼中的順序一致,但是它會保證程序最終執(zhí)行結(jié)果和代碼順序執(zhí)行的結(jié)果是一致的。

比如上面的代碼中,語句1和語句2誰先執(zhí)行對最終的程序結(jié)果并沒有影響,那么就有可能在執(zhí)行過程中,語句2先執(zhí)行而語句1后執(zhí)行。

但是要注意,雖然處理器會對指令進(jìn)行重排序,但是它會保證程序最終結(jié)果會和代碼順序執(zhí)行結(jié)果相同,那么它靠什么保證的呢?再看下面一個(gè)例子:

int a = 10;    //語句1
int r = 2;    //語句2
a = a + 3;    //語句3
r = a*a;     //語句4

這段代碼有4個(gè)語句,那么可能的一個(gè)執(zhí)行順序是:這段代碼有4個(gè)語句,那么可能的一個(gè)執(zhí)行順序是:

那么可不可能是這個(gè)執(zhí)行順序呢: 語句2 語句1 語句4 語句3

不可能,因?yàn)樘幚砥髟谶M(jìn)行重排序時(shí)是會考慮指令之間的數(shù)據(jù)依賴性,如果一個(gè)指令I(lǐng)nstruction 2必須用到Instruction 1的結(jié)果,那么處理器會保證Instruction 1會在Instruction 2之前執(zhí)行。

雖然重排序不會影響單個(gè)線程內(nèi)程序執(zhí)行的結(jié)果,但是多線程呢?下面看一個(gè)例子:

//線程1:
context = loadContext();   //語句1
inited = true;             //語句2
//線程2:
while(!inited ){
  			sleep()
}
doSomethingwithconfig(context);

上面代碼中,由于語句1和語句2沒有數(shù)據(jù)依賴性,因此可能會被重排序。假如發(fā)生了重排序,在線程1執(zhí)行過程中先執(zhí)行語句2,而此是線程2會以為初始化工作已經(jīng)完成,那么就會跳出while循環(huán),去執(zhí)行doSomethingwithconfig(context)方法,而此時(shí)context并沒有被初始化,就會導(dǎo)致程序出錯(cuò)。

從上面可以看出,指令重排序不會影響單個(gè)線程的執(zhí)行,但是會影響到線程并發(fā)執(zhí)行的正確性。

也就是說,要想并發(fā)程序正確地執(zhí)行,必須要保證原子性、可見性以及有序性。只要有一個(gè)沒有被保證,就有可能會導(dǎo)致程序運(yùn)行不正確。

主站蜘蛛池模板: 在线观看成人免费视频播放 | 性欧美xxxx视频在线观看 | 91成年人免费视频 | 一级片黄色a| 国产v国产v片大片线观看网站 | 老妇女人一级毛片 | 成人影院vs一区二区 | 在线观看不卡 | 欧美日韩免费看 | 亚洲精品天堂在线 | 麻豆导航| 国产一区亚洲二区 | 一级毛片在线播放免费 | 中文字幕一区二区三区精品 | 黄色免费看看 | 一级毛片成人免费看免费不卡 | 在线看欧美成人中文字幕视频 | 波多野吉衣 免费一区 | 在线黄站| 久久免费高清视频 | 日批免费视频不要会员 | 一级免费黄色大片 | 日本亚洲欧美美色 | 小娜的荡高h放荡日记 | 韩国xxxx色视频在线观看 | 国产在线视频欧美亚综合 | 亚洲超大尺度激情啪啪人体 | 看特级毛片 | 成年免费大片黄在线观看com | jizzjizz老师太多水日本 | 在线欧美不卡 | 黄色片免费观看网站 | 亚洲精品tv久久久久久久久久 | 色88888久久久久久影院 | 日韩美女视频在线 | 黄色按摩视频 | 污网站免费在线观看 | 99ri精品视频在线观看播放 | 欧美高清欧美videosex | 免费在线观看成人 | 日韩在线www|