java中的異常和處理詳解 Java如何解決可見性和有序性的問題?
Java如何解決可見性和有序性的問題?首先,我們需要了解為什么會有 "能見度和和 "時(shí)機(jī)與時(shí)機(jī)問題,然后讓 讓我們看看Java是如何解決這兩個(gè)問題的??梢娦院蜁r(shí)間問題導(dǎo)致以下原因:搶占式任務(wù)執(zhí)行:現(xiàn)代
Java如何解決可見性和有序性的問題?
首先,我們需要了解為什么會有 "能見度和和 "時(shí)機(jī)與時(shí)機(jī)問題,然后讓 讓我們看看Java是如何解決這兩個(gè)問題的。
可見性和時(shí)間問題導(dǎo)致以下原因:
搶占式任務(wù)執(zhí)行:現(xiàn)代CPU多任務(wù)執(zhí)行模式是 "先發(fā)制人 ",它的總控制權(quán)在操作系統(tǒng)手里,操作系統(tǒng)會把執(zhí)行時(shí)間片依次分配給需要CPU執(zhí)行的任務(wù)。超過時(shí)間后,操作系統(tǒng)將剝奪當(dāng)前任務(wù)的CPU訪問權(quán),將其放在隊(duì)列的末尾,最后分配時(shí)間片...
存儲速度差異:每個(gè)存儲的執(zhí)行速度不同。越靠近CPU,存儲速度越快,相對容量越小。不可能一次把執(zhí)行程序需要的所有數(shù)據(jù)都加載到寄存器中,所以有一個(gè)加載和存儲的過程,這就影響了所謂的 "能見度和
指令重排:現(xiàn)代微處理器大多會采用亂序執(zhí)行的方法(簡稱OoOE或oOE),在條件允許的情況下直接運(yùn)行當(dāng)前能夠立即執(zhí)行的后續(xù)指令,避免等待獲取下一條指令所需的數(shù)據(jù)。通過亂序執(zhí)行技術(shù),處理器可以大大提高執(zhí)行效率。除了處理器,常見Java運(yùn)行時(shí)環(huán)境中的JIT編譯器也做指令重排序操作,即生成的機(jī)器指令與字節(jié)碼指令的順序不同。
解決問題的方法很簡單,就是強(qiáng)制多線程單線程化。
只有兩種解決方案:
記憶障礙
鎖
讓 讓我們來看看JVM的內(nèi)存模型,我們將基于這個(gè)模型來簡單解釋一下。
內(nèi)存屏障內(nèi)存屏障是通過volatile關(guān)鍵字在Java中體現(xiàn)的。Volatile將在適當(dāng)?shù)牡胤教砑右韵滤膫€(gè)內(nèi)存屏障。
LoadLoad barrier:對于這樣的語句,Load1 Load Load2,保證Load1要讀取的數(shù)據(jù)在Load2要讀取的數(shù)據(jù)和后續(xù)讀取操作被訪問之前被讀取。
StoreStore barrier:對于這樣一個(gè)語句,Store1 StoreStore Store2,保證Store1的寫操作在Store2和后續(xù)寫操作執(zhí)行之前對其他處理器可見。
LoadStore barrier:對于這樣一個(gè)語句,Load1 LoadStore Store2,在Store2和后續(xù)的寫操作被刷出之前,Load1要讀取的數(shù)據(jù)保證被完全讀取。
StoreLoad barrier:對于這樣的語句Store1 StoreLoad Load2,在執(zhí)行Load2和所有后續(xù)讀取操作之前,Store1的寫入保證對所有處理器可見。它的開銷是四個(gè)障礙中最大的。在大多數(shù)處理器實(shí)現(xiàn)中,這種屏障是通用屏幕。屏障,具有其他三種記憶屏障的功能。
內(nèi)存屏障只能保證可見性,而不能保證計(jì)時(shí)。也就是說,內(nèi)存屏障只是解決了線程A修改的內(nèi)容可以被線程B立即讀取的問題。
Java中的鎖根據(jù)性質(zhì)可以分為悲觀鎖和樂觀鎖。悲觀鎖基于鎖指令實(shí)現(xiàn),樂觀鎖基于CAS實(shí)現(xiàn)。
悲觀鎖是通過monitorenter和monitorexit兩個(gè)指令實(shí)現(xiàn)的,這兩個(gè)指令之間的指令不能重排和互斥。假設(shè)線程A和線程B同時(shí)執(zhí)行一段代碼,線程A首先通過monitorenter獲得鎖,那么線程B只能在線程A執(zhí)行monitorexit之前等待。
CAS是CompareAndSet,Java是通過spinning和CPU級指令實(shí)現(xiàn)的。有關(guān)詳細(xì)信息,請參考JUC實(shí)施。假設(shè)有一個(gè)變量c,初始值為3。線程A和線程B同時(shí)修改這個(gè)變量。A和B同時(shí)得到變量C的值。a首先修改它并將值更改為4。b試圖修改它,但是發(fā)現(xiàn)c的值現(xiàn)在是4而不是3,于是他等待spin,然后重新進(jìn)行修改操作,將4改為5。
ThreadLocal最后說ThreadLocal。ThreadLocal是局部線程變量,即在線程中直接使用公共變量,修改不影響外界。它遠(yuǎn)遠(yuǎn)沒有解決 "能見度和和 "時(shí)機(jī)與時(shí)機(jī)。它只保證當(dāng)前線程中的修改不影響其他線程,其他線程的修改不影響當(dāng)前線程。
java中的main函數(shù)拋出的異常由誰處理?
java中main函數(shù)拋出的異常由JVM(java虛擬機(jī))處理。
在java程序中,如果異常被拋出,直到在try{}catch時(shí)被捕獲;如果仍然沒有捕獲到main方法(main method),那么異常將由java虛擬機(jī)(java運(yùn)行時(shí)環(huán)境)處理。