JVM內(nèi)存管理
概述
volatile 是輕量級(jí)的 synchronized注整。volatile 作用于共享變量郭膛,具備了“鎖”的特性,這是為了確保共享變量能被準(zhǔn)確和一致性地更新斧账,這是 volatile 的可見性著蟹。同時(shí),它也閹割了 scnchronized 的一寫功能中贝,比如:原子性囤捻。
內(nèi)存模型
圖如篇首。
首先我們應(yīng)該明白CPU是執(zhí)行命令的場(chǎng)所邻寿,當(dāng)需要處理數(shù)據(jù)時(shí)蝎土,CPU會(huì)從主內(nèi)存(計(jì)算機(jī)內(nèi)存)中取值,這樣很慢绣否。后來有了CPU高速緩存(cache)誊涯,也就是CPU上有一小塊存儲(chǔ)空間緩存了從主內(nèi)存中獲取的數(shù)據(jù),CPU直接讀取cache枝秤,效率大增。
然后慷嗜,問題出現(xiàn)了淀弹,待處理的數(shù)據(jù)并非是主內(nèi)存中的原型,而是一個(gè)副本庆械,在多線程場(chǎng)景下薇溃,這個(gè)副本的處理結(jié)果很有可能會(huì)失控。這個(gè)問題也就是緩存一致性問題缭乘,即cache和主內(nèi)存數(shù)據(jù)同步問題沐序。目前我知道解決緩存一致性問題有兩種方案:
通過在總線加LOCK鎖
通過緩存一致性協(xié)議
第一種是通過獨(dú)占CPU方式實(shí)現(xiàn),同一時(shí)間只有一個(gè)CPU在運(yùn)行堕绩,效率低下策幼。
第二種允許多核處理,并且讓共享副本在線程之間具有可見性奴紧。
可見性
通過 volatile 實(shí)現(xiàn)了緩存一致性特姐,其工作原理如下:
當(dāng)某個(gè)CPU在寫數(shù)據(jù)時(shí),如果發(fā)現(xiàn)操作的變量是共享變量黍氮,則會(huì)通知其他CPU告知該變量的緩存行是無(wú)效的唐含,因此其他CPU在讀取該變量時(shí),發(fā)現(xiàn)其無(wú)效會(huì)重新從主存中加載數(shù)據(jù)沫浆。
volatile 的可見性只針對(duì)當(dāng)CPU從主內(nèi)存中加載共享變量的時(shí)候捷枯。但是當(dāng)線程A、B同時(shí)加載了共享變量i专执,后者說線程A先加載了i淮捆,在A將i寫入之前,B加載了i,B加載的i仍然是主內(nèi)存中i的初始值争剿。
非原子性
線程內(nèi)存與主內(nèi)存的交互過程如下:
主要有以下5項(xiàng)操作:
read:從主內(nèi)存中讀取變量
load:復(fù)制變量到線程本地內(nèi)存作為副本
use:運(yùn)算副本
assign:給副本賦值
store:副本寫入線程本地內(nèi)存?直播系統(tǒng)開發(fā)找上海捌躍網(wǎng)絡(luò)科技有限公司?17621291122
write:線程內(nèi)存中的共享副本刷新主內(nèi)存中的共享變量
上一章節(jié)——“可見性”中已經(jīng)聲明 volatile 的可見性只針對(duì)當(dāng)CPU從主內(nèi)存中加載共享變量的時(shí)候已艰,即load之前,一旦load蚕苇,無(wú)論主內(nèi)存中的共享變量發(fā)生了什么哩掺,副本的值不會(huì)被主內(nèi)存同步。也就是說涩笤,volatile不具有原子性嚼吞。
網(wǎng)友解答:
volatile的非原子性:線程工作內(nèi)容中的值從主內(nèi)存中直接加載,一旦加載完成蹬碧,就不會(huì)再產(chǎn)生對(duì)應(yīng)的變化舱禽。JVM保證的是從主內(nèi)存中加載到線程工作內(nèi)存中的值是最新的,但是無(wú)法保證原子性恩沽。 volatile解決的是變量讀時(shí)的可見性問題誊稚,無(wú)法保證原子性。
package com.zhoupq.multiThread.Volatile;
public class VolatileDemo implements Runnable
{
static volatile int i = 1;br/>@Override
public void run()
{
System.out.println(Thread.currentThread().getName() + ": " + i + ", "
}
public static void main(String[] args)
{
Thread t1 = new Thread(new VolatileDemo(), "A");
Thread t2 = new Thread(new VolatileDemo(), "B");
Thread t3 = new Thread(new VolatileDemo(), "C");
Thread t4 = new Thread(new VolatileDemo(), "D");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/
A: 1, 2
B: 1, 3
C: 3, 4
D: 4, 5
/
網(wǎng)友解答:
i 和+(++i)是兩條指令飒箭,會(huì)發(fā)生這種情況:
假設(shè)當(dāng)前i為1狼电,線程A執(zhí)行+i,線程B執(zhí)行+i弦蹂,然后線程A執(zhí)行+(++i)肩碟,這時(shí)i=2,然后線程B執(zhí)行+(++i)凸椿,這時(shí)i=3腾务,線程A輸出(1, 2),線程B輸出(1, 3)削饵。
小結(jié)
volatile 保證可見性
volatile 不保證原子性
volatile 不能解決并發(fā)計(jì)算問題
轉(zhuǎn)自:http://blog.51cto.com/13917525/2320095