主內(nèi)存間與工作內(nèi)存
Java內(nèi)存模型規(guī)定了所有的變量都存儲(chǔ)在主內(nèi)存中,每條線程有自己的工作內(nèi)存

內(nèi)存間交互操作
- lock(鎖定):作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)識(shí)為一條線程獨(dú)占的狀態(tài)
- unlock(解鎖):作用于主內(nèi)存的變量,把一個(gè)處于鎖定狀態(tài)的變量釋放出來,釋放后的變量才可以被其他線程鎖定
- read(讀?。鹤饔糜谥鲀?nèi)存的變量,把一個(gè)變量的值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的load動(dòng)作使用
- use(使用):作用于工作內(nèi)存的變量,把工作內(nèi)存中一個(gè)變量的值傳遞給執(zhí)行引擎
- assign(賦值):作用于工作內(nèi)存的變量,把一個(gè)從執(zhí)行引擎接受到的值賦給工作內(nèi)存的變量
- store(存儲(chǔ)):作用于工作內(nèi)存的變量,把工作內(nèi)存中一個(gè)變量的值傳送到主內(nèi)存中
- write(寫入):作用于主內(nèi)存的變量,把store操作從工作內(nèi)存得到的變量的值放入主內(nèi)存的變量中

volatile關(guān)鍵字
volatile關(guān)鍵字可以說是Java虛擬機(jī)提供的最輕量級(jí)的同步機(jī)制,但是它并不容易完全被正確、完整地理解,以至于很多程序員都不習(xí)慣使用它,遇到多線程數(shù)據(jù)競(jìng)爭(zhēng)問題的時(shí)候就一律使用synchronized來進(jìn)行同步。了解volatile變量的語義對(duì)了解多線程操作的很多特性很有意義。
- volatile的可見性:保證此變量對(duì)所有線程的可見性,但不意味著是立即可見的
public class Counter {
public volatile static int count = 0;
public static void inc() {
count++;
}
public static void main(String[] args) {
//同時(shí)啟動(dòng)1000個(gè)線程,去進(jìn)行i++計(jì)算,看看實(shí)際結(jié)果
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Counter.inc();
}
}).start();
}
//這里每次運(yùn)行的值都有可能不同,可能為1000
System.out.println("運(yùn)行結(jié)果:Counter.count=" + Counter.count);
}
}
在本例中count變量用volatile關(guān)鍵字進(jìn)行修飾,保證了線程均可以取到count變量,但是由于count++是一個(gè)非原子操作(下一小節(jié)介紹),這個(gè)操作需要執(zhí)行4條指令才能完成,在此期間如果有另一個(gè)線程進(jìn)行讀取操作,隨后原來的線程會(huì)將數(shù)據(jù)寫入,另一個(gè)線程又會(huì)進(jìn)行寫入。例如第一個(gè)線程讀取count的時(shí)候,count=20,在執(zhí)行++操作的時(shí)候,有另一個(gè)線程讀取count,此時(shí)count尚未完成++,所以值還是20。在后一個(gè)線程進(jìn)行操作時(shí),前一個(gè)線程執(zhí)行完,將count寫入21,當(dāng)后一個(gè)線程完成后,仍舊寫入21, 所以本該寫入22的數(shù)值就這樣變小了。
- volatile的禁止指令重排序優(yōu)化
相比于synchronized,volatile總開銷要小,這是由于volatile變量的讀操作性能消耗與普通變量差不多,寫操作可能會(huì)慢一點(diǎn)。
原子性、可見性和有序性
原子性(Atomicity)
由Java內(nèi)存模型來直接保證的原子性變量操作包括read、load、assign、use、store、write,基本數(shù)據(jù)類型的訪問讀寫是具備原子性的(long和double是例外)。synchronized使用了lock和unlock操作,所以synchronized塊之間的操作也具有原子性。
可見性(Visibility)
可見性是指當(dāng)一個(gè)線程修改了共享變量的值,其他線程能夠立即得知這個(gè)修改。無論是普通變量還是volatile變量都是如此,區(qū)別是volatile的特殊規(guī)則保證了新值能立即同步到主內(nèi)存,以及每次使用前立即從主內(nèi)存刷新。volatile保證了多線程操作時(shí)變量的可見性,而普通變量則不能保證這一點(diǎn)。synchronized和final也能夠?qū)崿F(xiàn)可見性。
有序性(Ordering)
volatile和synchronized保證線程之間操作的有序性