面試官問題:1.Java并發(fā)這塊了解的怎么樣?說說你對volatile關(guān)鍵字的理解? 回答: volatile是JVM提供的輕量級的同步機(jī)制 1.保證可見性 2.保證有序性,禁止指令重排 3.不保證原子性(需要借助synchronized或者CAS) 面試官問題:2.能不能詳細(xì)說下什么是內(nèi)存可見性? 回答: 一問到內(nèi)存的可見性,volatile相關(guān)的,直接就把JMM內(nèi)存模型搬出來好吧。先放圖,然后再表演。 以下是俺個人的回答,有不足或漏洞,歡迎大家更正指出! 所謂可見性,是指當(dāng)一條線程修改了共享變量的值,新值對于其他線程來說是可以立即得知的 每個線程都有自己獨(dú)立的工作區(qū)間,為了匹配CPU的運(yùn)行速度,他們不會直接從內(nèi)存中讀取數(shù)據(jù),而是將數(shù)據(jù)拷貝一份到CPU緩存中(即每個線程自己的工作內(nèi)存),他們之間的相互交互,是通過內(nèi)存來完成的。 根據(jù)JMM內(nèi)存模型的8大原子操作,每個線程在j將數(shù)據(jù)操作完stroe回主存之前,會加lock指令來鎖定內(nèi)存區(qū)域的緩存(緩存行鎖定),根據(jù)MESI緩存一致性協(xié)議,總線通過偵聽器發(fā)現(xiàn)數(shù)據(jù)被修改,會立即讓其他線程工作內(nèi)存中不一致的副本立即失效。 等到當(dāng)前線程將更改后的數(shù)據(jù)write回主存后,立即執(zhí)行unlock指令。 此時(shí),其他線程再重新讀取更新后的數(shù)據(jù),再拷貝到自己的工作內(nèi)存。總線偵聽機(jī)制會在總線上檢測線程的數(shù)據(jù),發(fā)現(xiàn)有線程做了更改時(shí)準(zhǔn)備store回主內(nèi)存時(shí),它就會立刻將其他線程工作內(nèi)存中的副本置位無效,然后從新到主存獲取更新后的值。 除了使用 volatile 關(guān)鍵字來保證內(nèi)存可見性之外,使用synchronized或Lock鎖也能保證變量的內(nèi)存可見性。只是相比而言使用 volatile關(guān)鍵字開銷更小,是輕量級的鎖。 這就是內(nèi)存可見性的原理。 面試官問題:3.volatile關(guān)鍵字是怎么保證有序性的?什么又是重排序呢? 回答: 使用volatile關(guān)鍵字修飾共享變量便可以禁止指令重排序。若用volatile修飾共享變量,在JVM底層volatile是采用“內(nèi)存屏障”來實(shí)現(xiàn)禁止特定類型的處理器重排序。加入volatile關(guān)鍵字時(shí),會多出一個lock前綴指令,lock前綴指令實(shí)際上相當(dāng)于一個內(nèi)存屏障(也成內(nèi)存柵欄),內(nèi)存屏障會提供3個功能: 1.它確保指令重排序時(shí)不會把其后面的指令排到內(nèi)存屏障之前的位置,也不會把前面的指令排到內(nèi)存屏障的后面;即在執(zhí)行到內(nèi)存屏障這句指令時(shí),在它前面的操作已經(jīng)全部完成; 2.它會強(qiáng)制將對緩存的修改操作立即寫入主存; 3.如果是寫操作,它會導(dǎo)致其他CPU中對應(yīng)的緩存行無效。 JMM具備一些先天的有序性,通過Happens-Before原則就可以保證的一定的有序性。 面試官問題:4.volatile能保證可見性和有序性,但是能保證原子性嗎?為什么? 回答: |
|