尚硅谷Java大廠面試題第2季,面試必刷,跳槽大廠神器

1.并發(fā)和并行有什么區(qū)別?
并發(fā)就像秒殺,多個線程去訪問同一個資源;并行就是各種事情同時去做(比如說我邊聽音樂邊看知乎邊聊天)。
2.什么是volatile?
volatile是java虛擬機(jī)提供的輕量級的同步機(jī)制。
3.volatile有什么特性?
①保證可見性。
②不保證原子性。
③禁止指令重排。
1.JMM(java內(nèi)存模型)本身是一種抽象的概念,它并不真實(shí)存在,它描述的是一組規(guī)則或規(guī)范,通過這組規(guī)范定義了程序中的各個變量(包括實(shí)例字段,靜態(tài)字段和構(gòu)成數(shù)組對象的元素)的訪問方式。
2.硬件速度:硬盤 < 內(nèi)存 < CPU,CPU和內(nèi)存之間存在著一片區(qū)域叫緩存cache。
3.JMM內(nèi)存模型的特性:
①可見性:一個線程修改了主物理內(nèi)存之后,其他線程第一時間會獲得通知,這種第一時間通知的機(jī)制,就叫做java內(nèi)存模型的可見性。
1.JMM的三大特性:可見性、原子性、有序性,這三個特性是大多數(shù)多線程開發(fā)需要遵守的規(guī)范。
2.volatile可見性的代碼驗(yàn)證說明:
// todo
2.原子性是什么意思?
不可分割,完整性,也即某個線程正在做某個業(yè)務(wù)時,中間不可以被加塞或者被分割。需要保證整體完整,要么同時成功,要么同時失敗。
3.Thread.yield() 方法,使當(dāng)前線程由執(zhí)行狀態(tài),變成為就緒狀態(tài),讓出cpu時間,在下一個線程執(zhí)行時候,此線程有可能被執(zhí)行,也有可能沒有被執(zhí)行(誰先搶到誰就先執(zhí)行)。
4.volatile不保證原子性的代碼驗(yàn)證說明:
// todo
1.n++操作,實(shí)際上被拆分成了3個指令:
①執(zhí)行g(shù)etfield拿到原始的n(各個線程從主物理內(nèi)存中拿到初始值n);
②執(zhí)行iadd進(jìn)行加1的操作(各個線程在其工作內(nèi)存中執(zhí)行+1的操作);
③執(zhí)行putfield寫,把累加之后的值寫回主內(nèi)存。
2.volatile不保證原子性的理論原因: 各個線程出現(xiàn)了寫值丟失的情況(也可以稱之為寫覆蓋)。
1.如何解決原子性?
①加syconized(殺雞焉用牛刀,不合適);
②使用JUC下帶原子(Atomic)的類,例如:AtomicInteger;
1.計算機(jī)在執(zhí)行程序時,為了提高性能,編譯器和處理器常常會對指令做重排。會分為以下3種:
編譯器優(yōu)化的重排、指令并行的重排、內(nèi)存系統(tǒng)的重排。
1.單線程環(huán)境里面確保程序最終執(zhí)行結(jié)果和代碼順序執(zhí)行的結(jié)果一致(單線程環(huán)境下,不存在指令重排)。
2.處理器在進(jìn)行重排序時必須要考慮指令之間的依賴性。
3.多線程環(huán)境中線程交替執(zhí)行,由于編譯器優(yōu)化重排的存在,兩個線程中使用的變量能否保證一致性是無法確定的,結(jié)果無法預(yù)測。
4.禁止指令重排的小總結(jié):
// todo
5.線程安全性獲得保證:
①工作內(nèi)存與主內(nèi)存同步延遲現(xiàn)象導(dǎo)致的可見性問題如何解決?
答:可以使用synchronized或者volatile關(guān)鍵字解決,它們都可以使一個線程修改后的變量立即對其他線程可見。
②對于指令重排導(dǎo)致的可見性問題和有序性問題,如何解決?
答:可以利用volatile關(guān)鍵字解決,因?yàn)関olatile的另外一個作用就是禁止重排序優(yōu)化。
1.在多線程環(huán)境下,單例模式會存在安全問題,可以使用DCL模式去解決(Double Check Lock雙端檢鎖機(jī)制,在加鎖之前和枷鎖之后都進(jìn)行一次判斷)。
CAS:compare and swap
1.為什么不用synchronized而用CAS?
答:CAS是樂觀鎖的一種實(shí)現(xiàn)機(jī)制,一種無鎖機(jī)制 在線程等待時間短的情況下,性能更高
2.

Unsafe是CAS的核心類,由于Java方法無法直接訪問底層系統(tǒng),需要通過本地(native)方法來訪問,Unsafe相當(dāng)于一個后門,基于該類可以直接操作特定內(nèi)存的數(shù)據(jù)。Unsafe類存在于sun.misc包中,其內(nèi)部方法操作可以像C的指針一樣直接操作內(nèi)存,因?yàn)镴ava中CAS操作的執(zhí)行依賴于Unsafe類的方法。
①注意Unsafe類中的所有方法都是native修飾的,也就是說Unsafe類中的方法都直接調(diào)用操作系統(tǒng)底層資源執(zhí)行相應(yīng)任務(wù)。
②變量valueOffset,表示該變量值在內(nèi)存中的偏移地址,因?yàn)閁nsafe就是根據(jù)內(nèi)存偏移地址獲取數(shù)據(jù)的。
③變量value用volatile修飾,保證了多線程之間的內(nèi)存可見性。
3.CAS是什么?
答:CAS的全稱為Compare-And-Swap,它是一條CPU并發(fā)原語。
它的功能是判斷內(nèi)存某個位置的值是否為預(yù)期值,如果是則更改為新的值,這個過程是原子的。
1.CAS的缺點(diǎn):
循環(huán)時間長,會給CPU帶來很大的開銷
只能保證一個共享變量的原子操作
ABA問題
1.ABA問題如何解決?
使用AtomicStampedReference類生成版本號
1.ArrayList是線程不安全的,在多線程環(huán)境下,會報錯:
java.util.ConcurrentModificationException
解決方法之一:Vector
解決方法之二:Collections.synchronizedList()
解決方法之三:CopyOnWriteArrayList(寫時復(fù)制讀寫分離的思想,最推薦)
2.集合并發(fā)異常的導(dǎo)致原因:
并發(fā)爭搶導(dǎo)致,參考花名冊簽名情況,一個人正在寫入,另一個同學(xué)過來爭搶,導(dǎo)致數(shù)據(jù)不一致異常,并發(fā)修改異常。
HashSet線程不安全的解決方法:
- Collections.synchronizedSet(new HashSet<>())
- CopyOnWriteArraySet<>()(推薦)
解決方法:
- HashTable
- Collections.synchronizedMap(new HashMap<>())
- ConcurrentMap<>()(推薦)
1.公平和非公平鎖,是什么?:
公平鎖 是指多個線程按照申請鎖的順序來獲取鎖,類似排隊(duì)打飯,先來后到。
非公平鎖 是指多個線程獲取鎖的順序并不是按照申請鎖的順序,有可能后中請的線程比先中請的線程優(yōu)先獲取鎖。在高并發(fā)的情況下,有可能會造成優(yōu)先級反轉(zhuǎn)或者饑餓現(xiàn)象
2.并發(fā)包中ReentrantLock的創(chuàng)建可以指定構(gòu)造函數(shù)的boolean類型來得到公平鎖或非公平鎖,默認(rèn)是非公平鎖。
3.對于ReentrantLock而言,默認(rèn)是非公平鎖。非公平鎖的優(yōu)點(diǎn)在于吞吐量比公平鎖大。
4.對于Synchronized而言,也是一種非公平鎖。
指的是同一線程外層函數(shù)獲得鎖之后,內(nèi)層遞歸函數(shù)仍然能獲取該鎖的代碼,在同一個線程在外層方法獲取鎖的時候,在進(jìn)入內(nèi)層方法會自動獲取鎖。
也即是說,線程可以進(jìn)入任何一個它已經(jīng)擁有的鎖所同步著的代碼塊。
ReentrantLock/synchronized就是一個典型的可重入鎖。
可重入鎖最大的作用是避免死鎖。