話不多說(shuō),,先上一張圖 java內(nèi)存模(jie)型(gou) 沒(méi)錯(cuò),我們今天聊的東西,,跟他沒(méi)啥關(guān)系,。 上面這是java的內(nèi)存結(jié)構(gòu)(我就是忽悠你們來(lái)的)。 今兒主要先聊一聊java的內(nèi)存模型(嗯,,也不是非想跟你們聊,,主要是標(biāo)題得從這玩意兒來(lái)引出)。 但是也不能干聊不是,?想起兄弟們?cè)?jīng)對(duì)我靈魂的拷問(wèn)(無(wú)圖言屌),,所以我就又從網(wǎng)上盜了一張圖。 來(lái)來(lái)來(lái),,看圖說(shuō)話: java真·內(nèi)存模型 1.java中所有的變量都是存在主內(nèi)存里的,。 2.各自的線程在工作的時(shí)候會(huì)自己拿到一塊工作內(nèi)存。里面保存了該線程用到的變量的副本,。 3.線程對(duì)變量的操作,,都是對(duì)自己工作內(nèi)存中變量的操作,不能操作主內(nèi)存,。 4.最終工作內(nèi)存中的數(shù)據(jù)是需要同步回主內(nèi)存,,來(lái)完成主內(nèi)存中變量的更新的。 舉個(gè)例子吧: 就好比主內(nèi)存就是大哥,,線程就是小弟,,大哥每天督促小弟們干活,小弟們彼此不怎么交流,,每天就是干了活,,然后自己找個(gè)本記下來(lái),找時(shí)間告訴大哥,。 那么咱們來(lái)看下面的這一個(gè)場(chǎng)景: 大哥說(shuō)讓仨小弟進(jìn)點(diǎn)兒貨,。讓一個(gè)小弟聯(lián)系貨源,一個(gè)小弟聯(lián)系運(yùn)輸公司,,一個(gè)小弟聯(lián)系裝卸工,。小弟1去聯(lián)系貨源了,聯(lián)系好了告訴大哥,,“貨源聯(lián)系好了”,。這時(shí)候小弟2來(lái)了,一聽(tīng)貨源好了,,就去聯(lián)系運(yùn)輸公司了,。運(yùn)輸公司聯(lián)系好了,小弟2還沒(méi)回去告訴大哥呢,,小弟3跑過(guò)去問(wèn)大哥了,,一聽(tīng)大哥說(shuō)貨源好了,,也跑出去聯(lián)系運(yùn)輸公司了。結(jié)果來(lái)了倆運(yùn)輸公司,,對(duì)著成堆的貨物干瞪眼,。 這里面有幾個(gè)問(wèn)題呢? 1.小弟2忙活清了,,應(yīng)該打個(gè)電話趕緊通知大哥,,他找到運(yùn)輸公司了。 2.大哥知道小弟2出去忙活事情了,,小弟3這時(shí)候來(lái)了,,大哥應(yīng)該別讓小弟3著急,等小弟2干完了,,小弟3再上,。 3.小弟2要是告訴大哥,他出去找運(yùn)輸公司了,,大哥怎么還會(huì)讓小弟3接著去找運(yùn)輸公司呢,? 如果在這個(gè)場(chǎng)景里,我們會(huì)說(shuō),,這不一群智障么,,這種錯(cuò)誤都能發(fā)生,辦事不過(guò)腦子的么,?,!
其實(shí)呢,,上面闡述的三個(gè)問(wèn)題,,也就是我們java內(nèi)存模型在設(shè)計(jì)的時(shí)候,,所圍繞的三個(gè)問(wèn)題: 可見(jiàn)性,有序性和原子性,。(終于聊到重點(diǎn)了朋友們?。?/strong> 下面要上定義了!
Java內(nèi)存模型是通過(guò)將在工作內(nèi)存中的變量修改后的值同步到主內(nèi)存,在讀取變量前從主內(nèi)存刷新最新值到工作內(nèi)存中,,這種依賴主內(nèi)存的方式來(lái)實(shí)現(xiàn)可見(jiàn)性的,。
java內(nèi)存模型所保證的是,同線程內(nèi),,所有的操作都是由上到下的,,但是多個(gè)線程并行的情況下,則不能保證其操作的有序性,。
基本數(shù)據(jù)類型的訪問(wèn)都是原子性的(默認(rèn)64位,,32位的機(jī)器對(duì)long、double這種占8個(gè)字節(jié)的是非原子性的),,而針對(duì)非原子性的數(shù)據(jù),,多線程的訪問(wèn)則是不安全的。 以上是java內(nèi)存模型中,,單線程針對(duì)這三種問(wèn)題作出的最基本的控制,,但是并發(fā)編程的場(chǎng)景中, 多線程的出現(xiàn)會(huì)導(dǎo)致這三個(gè)問(wèn)題頻頻發(fā)生,。 那么聰明的你一定會(huì)問(wèn)了,,我們應(yīng)該如何去控制呢?(不問(wèn)的都拉出去彈雞兒) 一個(gè)一個(gè)來(lái): 可見(jiàn)性: volatile關(guān)鍵字:通過(guò)volatile關(guān)鍵字修飾內(nèi)存中的變量,,該變量在線程之間共享 其實(shí)對(duì)于可見(jiàn)性而言,,無(wú)論是普通變量還是volatile變量都是如此,區(qū)別在于:volatile的特殊規(guī)則保證了volatile變量值修改后的新值立刻同步到主內(nèi)存,,每次使用volatile變量前立即從主內(nèi)存中刷新,,因此volatile保證了多線程之間的操作變量的可見(jiàn)性,而普通變量則不能保證這一點(diǎn),。 但是volatile只是對(duì)關(guān)鍵字進(jìn)行了修飾,,保證了其可見(jiàn)性,而對(duì)于線程的有序性和變量的原子性,,volatile根本沒(méi)有什么卵用,,也就是什么意思呢? private static volatile int volatileCount = 0; private static void volatileCount() { for (int i = 0; i <>10; i++) { Executors.newFixedThreadPool(3).execute(() -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println('volatile count: ' + ++volatileCount); }); } } 代碼中的volatile,,加與不加,,沒(méi)多少區(qū)別。 原子性: private static AtomicInteger atomicCount = new AtomicInteger(0); private static void atomicCount() { for (int i = 0; i <>10; i++) { Executors.newFixedThreadPool(3).execute(() -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //atomicCount.incrementAndGet()方法的意思是讓其自增 1,等同于++ System.out.println('atomic count: ' + atomicCount.incrementAndGet()); }); } } // atomic count: 5 // atomic count: 1 // atomic count: 3 // atomic count: 2 // atomic count: 8 // atomic count: 10 // atomic count: 4 // atomic count: 6 // atomic count: 7 // atomic count: 9 結(jié)果也放在下面了,,可見(jiàn),,我們保證了它的唯一性,他是一定會(huì)自增到10的,。說(shuō)白了,,就是緩存鎖機(jī)制。
這段話也解釋了為什么雖然我們不能保證其有序性,但是,,我們依然能正常的自增到10,。 有序性: private static void synchronizedCount() { for (int i = 0; i <>10; i++) { Executors.newFixedThreadPool(3).execute(->() { public void run() { synchronized (MyClass.class) { // 通過(guò)synchronized關(guān)鍵字來(lái)保證線程之間的有序性 System.out.println('synchronized count: ' + ++synchronizedCount); } } }); } } 結(jié)果看上去很美好,,有序,,且從1到10,一個(gè)不差,。 public class Singleton{ private static volatile Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ if(instance==null){ instance=new Singleton(); } } } return instance; }} 如果不加volatile會(huì)有什么問(wèn)題呢,? OK,,基本說(shuō)清,,就此打住,老少爺們們,,咱下期再見(jiàn),。 |
|
來(lái)自: 昵稱60891057 > 《Java》