35. 并行和并發(fā)有什么區(qū)別刺彩?
- 并行是指兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生晨逝;而并發(fā)是指兩個(gè)或多個(gè)事件在同一時(shí)間間隔發(fā)生缎岗。
- 并行是在不同實(shí)體上的多個(gè)事件哈打,并發(fā)是在同一實(shí)體上的多個(gè)事件遏佣。
- 在一臺(tái)處理器上“同時(shí)”處理多個(gè)任務(wù)挖炬,在多臺(tái)處理器上同時(shí)處理多個(gè)任務(wù)。如hadoop分布式集群状婶。
所以并發(fā)編程的目標(biāo)是充分的利用處理器的每一個(gè)核意敛,以達(dá)到最高的處理性能馅巷。
36. 線(xiàn)程和進(jìn)程的區(qū)別?
簡(jiǎn)而言之草姻,進(jìn)程是程序運(yùn)行和資源分配的基本單位钓猬,一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線(xiàn)程撩独。進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元敞曹,而多個(gè)線(xiàn)程共享內(nèi)存資源,減少切換次數(shù)综膀,從而效率更高异雁。線(xiàn)程是進(jìn)程的一個(gè)實(shí)體,是cpu調(diào)度和分派的基本單位僧须,是比程序更小的能獨(dú)立運(yùn)行的基本單位纲刀。同一進(jìn)程中的多個(gè)線(xiàn)程之間可以并發(fā)執(zhí)行。
37. 守護(hù)線(xiàn)程是什么担平?
守護(hù)線(xiàn)程(即daemon thread)示绊,是個(gè)服務(wù)線(xiàn)程,準(zhǔn)確地來(lái)說(shuō)就是服務(wù)其他的線(xiàn)程暂论。
38. 創(chuàng)建線(xiàn)程有哪幾種方式面褐?
1. 繼承Thread類(lèi)創(chuàng)建線(xiàn)程類(lèi)
- 定義Thread類(lèi)的子類(lèi),并重寫(xiě)該類(lèi)的run方法取胎,該run方法的方法體就代表了線(xiàn)程要完成的任務(wù)展哭。因此把run()方法稱(chēng)為執(zhí)行體。
- 創(chuàng)建Thread子類(lèi)的實(shí)例闻蛀,即創(chuàng)建了線(xiàn)程對(duì)象匪傍。
- 調(diào)用線(xiàn)程對(duì)象的start()方法來(lái)啟動(dòng)該線(xiàn)程。
2. 通過(guò)Runnable接口創(chuàng)建線(xiàn)程類(lèi)
- 定義runnable接口的實(shí)現(xiàn)類(lèi)觉痛,并重寫(xiě)該接口的run()方法役衡,該run()方法的方法體同樣是該線(xiàn)程的線(xiàn)程執(zhí)行體。
- 創(chuàng)建 Runnable實(shí)現(xiàn)類(lèi)的實(shí)例薪棒,并依此實(shí)例作為T(mén)hread的target來(lái)創(chuàng)建Thread對(duì)象手蝎,該Thread對(duì)象才是真正的線(xiàn)程對(duì)象。
- 調(diào)用線(xiàn)程對(duì)象的start()方法來(lái)啟動(dòng)該線(xiàn)程俐芯。
3. 通過(guò)Callable和Future創(chuàng)建線(xiàn)程
- 創(chuàng)建Callable接口的實(shí)現(xiàn)類(lèi)棵介,并實(shí)現(xiàn)call()方法,該call()方法將作為線(xiàn)程執(zhí)行體吧史,并且有返回值邮辽。
- 創(chuàng)建Callable實(shí)現(xiàn)類(lèi)的實(shí)例,使用FutureTask類(lèi)來(lái)包裝Callable對(duì)象,該FutureTask對(duì)象封裝了該Callable對(duì)象的call()方法的返回值逆巍。
- 使用FutureTask對(duì)象作為T(mén)hread對(duì)象的target創(chuàng)建并啟動(dòng)新線(xiàn)程及塘。
- 調(diào)用FutureTask對(duì)象的get()方法來(lái)獲得子線(xiàn)程執(zhí)行結(jié)束后的返回值。
39. 說(shuō)一下 runnable 和 callable 有什么區(qū)別锐极?
- 有點(diǎn)深的問(wèn)題了笙僚,也看出一個(gè)Java程序員學(xué)習(xí)知識(shí)的廣度。
- Runnable接口中的run()方法的返回值是void灵再,它做的事情只是純粹地去執(zhí)行run()方法中的代碼而已肋层;
- Callable接口中的call()方法是有返回值的,是一個(gè)泛型翎迁,和Future栋猖、FutureTask配合可以用來(lái)獲取異步執(zhí)行的結(jié)果。
40. 線(xiàn)程有哪些狀態(tài)汪榔?
線(xiàn)程通常都有五種狀態(tài)蒲拉,創(chuàng)建、就緒痴腌、運(yùn)行雌团、阻塞和死亡。
- 創(chuàng)建狀態(tài)士聪。在生成線(xiàn)程對(duì)象锦援,并沒(méi)有調(diào)用該對(duì)象的start方法,這是線(xiàn)程處于創(chuàng)建狀態(tài)剥悟。
- 就緒狀態(tài)灵寺。當(dāng)調(diào)用了線(xiàn)程對(duì)象的start方法之后,該線(xiàn)程就進(jìn)入了就緒狀態(tài)区岗,但是此時(shí)線(xiàn)程調(diào)度程序還沒(méi)有把該線(xiàn)程設(shè)置為當(dāng)前線(xiàn)程略板,此時(shí)處于就緒狀態(tài)。在線(xiàn)程運(yùn)行之后躏尉,從等待或者睡眠中回來(lái)之后蚯根,也會(huì)處于就緒狀態(tài)后众。
- 運(yùn)行狀態(tài)胀糜。線(xiàn)程調(diào)度程序?qū)⑻幱诰途w狀態(tài)的線(xiàn)程設(shè)置為當(dāng)前線(xiàn)程,此時(shí)線(xiàn)程就進(jìn)入了運(yùn)行狀態(tài)蒂誉,開(kāi)始運(yùn)行run函數(shù)當(dāng)中的代碼教藻。
- 阻塞狀態(tài)。線(xiàn)程正在運(yùn)行的時(shí)候右锨,被暫停括堤,通常是為了等待某個(gè)時(shí)間的發(fā)生(比如說(shuō)某項(xiàng)資源就緒)之后再繼續(xù)運(yùn)行。sleep,suspend,wait等方法都可以導(dǎo)致線(xiàn)程阻塞悄窃。
- 死亡狀態(tài)讥电。如果一個(gè)線(xiàn)程的run方法執(zhí)行結(jié)束或者調(diào)用stop方法后,該線(xiàn)程就會(huì)死亡轧抗。對(duì)于已經(jīng)死亡的線(xiàn)程恩敌,無(wú)法再使用start方法令其進(jìn)入就緒
41. sleep() 和 wait() 有什么區(qū)別?
- sleep():方法是線(xiàn)程類(lèi)(Thread)的靜態(tài)方法横媚,讓調(diào)用線(xiàn)程進(jìn)入睡眠狀態(tài)纠炮,讓出執(zhí)行機(jī)會(huì)給其他線(xiàn)程,等到休眠時(shí)間結(jié)束后灯蝴,線(xiàn)程進(jìn)入就緒狀態(tài)和其他線(xiàn)程一起競(jìng)爭(zhēng)cpu的執(zhí)行時(shí)間恢口。因?yàn)閟leep() 是static靜態(tài)的方法,他不能改變對(duì)象的機(jī)鎖穷躁,當(dāng)一個(gè)synchronized塊中調(diào)用了sleep() 方法耕肩,線(xiàn)程雖然進(jìn)入休眠,但是對(duì)象的機(jī)鎖沒(méi)有被釋放问潭,其他線(xiàn)程依然無(wú)法訪(fǎng)問(wèn)這個(gè)對(duì)象看疗。
- wait():wait()是Object類(lèi)的方法,當(dāng)一個(gè)線(xiàn)程執(zhí)行到wait方法時(shí)睦授,它就進(jìn)入到一個(gè)和該對(duì)象相關(guān)的等待池两芳,同時(shí)釋放對(duì)象的機(jī)鎖,使得其他線(xiàn)程能夠訪(fǎng)問(wèn)去枷,可以通過(guò)notify怖辆,notifyAll方法來(lái)喚醒等待的線(xiàn)程
42. notify()和 notifyAll()有什么區(qū)別?
- 如果線(xiàn)程調(diào)用了對(duì)象的 wait()方法删顶,那么線(xiàn)程便會(huì)處于該對(duì)象的等待池中竖螃,等待池中的線(xiàn)程不會(huì)去競(jìng)爭(zhēng)該對(duì)象的鎖。
- 當(dāng)有線(xiàn)程調(diào)用了對(duì)象的 notifyAll()方法(喚醒所有 wait 線(xiàn)程)或 notify()方法(只隨機(jī)喚醒一個(gè) wait 線(xiàn)程)逗余,被喚醒的的線(xiàn)程便會(huì)進(jìn)入該對(duì)象的鎖池中特咆,鎖池中的線(xiàn)程會(huì)去競(jìng)爭(zhēng)該對(duì)象鎖。也就是說(shuō)录粱,調(diào)用了notify后只要一個(gè)線(xiàn)程會(huì)由等待池進(jìn)入鎖池腻格,而notifyAll會(huì)將該對(duì)象等待池內(nèi)的所有線(xiàn)程移動(dòng)到鎖池中,等待鎖競(jìng)爭(zhēng)啥繁。
- 優(yōu)先級(jí)高的線(xiàn)程競(jìng)爭(zhēng)到對(duì)象鎖的概率大菜职,假若某線(xiàn)程沒(méi)有競(jìng)爭(zhēng)到該對(duì)象鎖,它還會(huì)留在鎖池中旗闽,唯有線(xiàn)程再次調(diào)用 wait()方法酬核,它才會(huì)重新回到等待池中蜜另。而競(jìng)爭(zhēng)到對(duì)象鎖的線(xiàn)程則繼續(xù)往下執(zhí)行,直到執(zhí)行完了 synchronized 代碼塊嫡意,它會(huì)釋放掉該對(duì)象鎖举瑰,這時(shí)鎖池中的線(xiàn)程會(huì)繼續(xù)競(jìng)爭(zhēng)該對(duì)象鎖。
43. 線(xiàn)程的 run()和 start()有什么區(qū)別蔬螟?
每個(gè)線(xiàn)程都是通過(guò)某個(gè)特定Thread對(duì)象所對(duì)應(yīng)的方法run()來(lái)完成其操作的嘶居,方法run()稱(chēng)為線(xiàn)程體。通過(guò)調(diào)用Thread類(lèi)的start()方法來(lái)啟動(dòng)一個(gè)線(xiàn)程促煮。
- start()方法來(lái)啟動(dòng)一個(gè)線(xiàn)程邮屁,真正實(shí)現(xiàn)了多線(xiàn)程運(yùn)行。這時(shí)無(wú)需等待run方法體代碼執(zhí)行完畢,可以直接繼續(xù)執(zhí)行下面的代碼; 這時(shí)此線(xiàn)程是處于就緒狀態(tài)围段, 并沒(méi)有運(yùn)行。 然后通過(guò)此Thread類(lèi)調(diào)用方法run()來(lái)完成其運(yùn)行狀態(tài)芋忿, 這里方法run()稱(chēng)為線(xiàn)程體,它包含了要執(zhí)行的這個(gè)線(xiàn)程的內(nèi)容疾棵, Run方法運(yùn)行結(jié)束戈钢, 此線(xiàn)程終止。然后CPU再調(diào)度其它線(xiàn)程是尔。
- run()方法是在本線(xiàn)程里的殉了,只是線(xiàn)程里的一個(gè)函數(shù),而不是多線(xiàn)程的。 如果直接調(diào)用run(),其實(shí)就相當(dāng)于是調(diào)用了一個(gè)普通函數(shù)而已拟枚,直接待用run()方法必須等待run()方法執(zhí)行完畢才能執(zhí)行下面的代碼薪铜,所以執(zhí)行路徑還是只有一條,根本就沒(méi)有線(xiàn)程的特征恩溅,所以在多線(xiàn)程執(zhí)行時(shí)要使用start()方法而不是run()方法隔箍。
44. 創(chuàng)建線(xiàn)程池有哪幾種方式?
1. newFixedThreadPool(int nThreads)
創(chuàng)建一個(gè)固定長(zhǎng)度的線(xiàn)程池脚乡,每當(dāng)提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線(xiàn)程蜒滩,直到達(dá)到線(xiàn)程池的最大數(shù)量,這時(shí)線(xiàn)程規(guī)模將不再變化奶稠,當(dāng)線(xiàn)程發(fā)生未預(yù)期的錯(cuò)誤而結(jié)束時(shí)俯艰,線(xiàn)程池會(huì)補(bǔ)充一個(gè)新的線(xiàn)程。
2. newCachedThreadPool()
創(chuàng)建一個(gè)可緩存的線(xiàn)程池窒典,如果線(xiàn)程池的規(guī)模超過(guò)了處理需求蟆炊,將自動(dòng)回收空閑線(xiàn)程,而當(dāng)需求增加時(shí)瀑志,則可以自動(dòng)添加新線(xiàn)程,線(xiàn)程池的規(guī)模不存在任何限制。
3. newSingleThreadExecutor()
這是一個(gè)單線(xiàn)程的Executor劈猪,它創(chuàng)建單個(gè)工作線(xiàn)程來(lái)執(zhí)行任務(wù)昧甘,如果這個(gè)線(xiàn)程異常結(jié)束,會(huì)創(chuàng)建一個(gè)新的來(lái)替代它战得;它的特點(diǎn)是能確保依照任務(wù)在隊(duì)列中的順序來(lái)串行執(zhí)行充边。
4. newScheduledThreadPool(int corePoolSize)
創(chuàng)建了一個(gè)固定長(zhǎng)度的線(xiàn)程池,而且以延遲或定時(shí)的方式來(lái)執(zhí)行任務(wù)常侦,類(lèi)似于Timer浇冰。
45. 線(xiàn)程池都有哪些狀態(tài)?
線(xiàn)程池有5種狀態(tài):Running聋亡、ShutDown肘习、Stop、Tidying坡倔、Terminated漂佩。
線(xiàn)程池各個(gè)狀態(tài)切換框架圖:
詳細(xì)解釋見(jiàn):Java多線(xiàn)程線(xiàn)程池(4)--線(xiàn)程池的五種狀態(tài)
46. 線(xiàn)程池中 submit()和 execute()方法有什么區(qū)別?
接收的參數(shù)不一樣
- submit有返回值罪塔,而execute沒(méi)有
- submit方便Exception處理
47. 在 java 程序中怎么保證多線(xiàn)程的運(yùn)行安全投蝉?
線(xiàn)程安全在三個(gè)方面體現(xiàn):
- 原子性:提供互斥訪(fǎng)問(wèn),同一時(shí)刻只能有一個(gè)線(xiàn)程對(duì)數(shù)據(jù)進(jìn)行操作征堪,(atomic,synchronized)瘩缆;
- 可見(jiàn)性:一個(gè)線(xiàn)程對(duì)主內(nèi)存的修改可以及時(shí)地被其他線(xiàn)程看到,(synchronized,volatile)佃蚜;
- 有序性:一個(gè)線(xiàn)程觀察其他線(xiàn)程中的指令執(zhí)行順序咳榜,由于指令重排序,該觀察結(jié)果一般雜亂無(wú)序爽锥,(happens-before原則)涌韩。
48. 多線(xiàn)程鎖的升級(jí)原理是什么?
在Java中氯夷,鎖共有4種狀態(tài)臣樱,級(jí)別從低到高依次為:無(wú)狀態(tài)鎖,偏向鎖腮考,輕量級(jí)鎖和重量級(jí)鎖狀態(tài)雇毫,這幾個(gè)狀態(tài)會(huì)隨著競(jìng)爭(zhēng)情況逐漸升級(jí)。鎖可以升級(jí)但不能降級(jí)踩蔚。
鎖升級(jí)的圖示過(guò)程:
鎖共有4種狀態(tài)詳解: 【Java多線(xiàn)程策略 一】鎖的三種狀態(tài)切換
49. 什么是死鎖棚放?
死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象馅闽,若無(wú)外力作用飘蚯,它們都將無(wú)法推進(jìn)下去馍迄。此時(shí)稱(chēng)系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱(chēng)為死鎖進(jìn)程局骤。是操作系統(tǒng)層面的一個(gè)錯(cuò)誤攀圈,是進(jìn)程死鎖的簡(jiǎn)稱(chēng),最早在 1965 年由 Dijkstra 在研究銀行家算法時(shí)提出的峦甩,它是計(jì)算機(jī)操作系統(tǒng)乃至整個(gè)并發(fā)程序設(shè)計(jì)領(lǐng)域最難處理的問(wèn)題之一赘来。
50. 怎么防止死鎖?
死鎖的四個(gè)必要條件:
- 互斥條件:進(jìn)程對(duì)所分配到的資源不允許其他進(jìn)程進(jìn)行訪(fǎng)問(wèn)凯傲,若其他進(jìn)程訪(fǎng)問(wèn)該資源犬辰,只能等待,直至占有該資源的進(jìn)程使用完成后釋放該資源
- 請(qǐng)求和保持條件:進(jìn)程獲得一定的資源之后冰单,又對(duì)其他資源發(fā)出請(qǐng)求幌缝,但是該資源可能被其他進(jìn)程占有,此事請(qǐng)求阻塞球凰,但又對(duì)自己獲得的資源保持不放
- 不可剝奪條件:是指進(jìn)程已獲得的資源狮腿,在未完成使用之前,不可被剝奪呕诉,只能在使用完后自己釋放
- 環(huán)路等待條件:是指進(jìn)程發(fā)生死鎖后缘厢,若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系
這四個(gè)條件是死鎖的必要條件,只要系統(tǒng)發(fā)生死鎖甩挫,這些條件必然成立贴硫,而只要上述條件之 一不滿(mǎn)足,就不會(huì)發(fā)生死鎖伊者。
理解了死鎖的原因英遭,尤其是產(chǎn)生死鎖的四個(gè)必要條件,就可以最大可能地避免亦渗、預(yù)防和 解除死鎖挖诸。
所以,在系統(tǒng)設(shè)計(jì)法精、進(jìn)程調(diào)度等方面注意如何不讓這四個(gè)必要條件成立多律,如何確 定資源的合理分配算法,避免進(jìn)程永久占據(jù)系統(tǒng)資源搂蜓。
此外狼荞,也要防止進(jìn)程在處于等待狀態(tài)的情況下占用資源。因此帮碰,對(duì)資源的分配要給予合理的規(guī)劃相味。
51. ThreadLocal 是什么?有哪些使用場(chǎng)景殉挽?
線(xiàn)程局部變量是局限于線(xiàn)程內(nèi)部的變量丰涉,屬于線(xiàn)程自身所有拓巧,不在多個(gè)線(xiàn)程間共享。Java提供ThreadLocal類(lèi)來(lái)支持線(xiàn)程局部變量昔搂,是一種實(shí)現(xiàn)線(xiàn)程安全的方式玲销。但是在管理環(huán)境下(如 web 服務(wù)器)使用線(xiàn)程局部變量的時(shí)候要特別小心输拇,在這種情況下摘符,工作線(xiàn)程的生命周期比任何應(yīng)用變量的生命周期都要長(zhǎng)。任何線(xiàn)程局部變量一旦在工作完成后沒(méi)有釋放策吠,Java 應(yīng)用就存在內(nèi)存泄露的風(fēng)險(xiǎn)逛裤。
52.說(shuō)一下 synchronized 底層實(shí)現(xiàn)原理?
synchronized可以保證方法或者代碼塊在運(yùn)行時(shí)猴抹,同一時(shí)刻只有一個(gè)方法可以進(jìn)入到臨界區(qū)带族,同時(shí)它還可以保證共享變量的內(nèi)存可見(jiàn)性。
Java中每一個(gè)對(duì)象都可以作為鎖蟀给,這是synchronized實(shí)現(xiàn)同步的基礎(chǔ):
- 普通同步方法蝙砌,鎖是當(dāng)前實(shí)例對(duì)象
- 靜態(tài)同步方法,鎖是當(dāng)前類(lèi)的class對(duì)象
- 同步方法塊跋理,鎖是括號(hào)里面的對(duì)象
53. synchronized 和 volatile 的區(qū)別是什么择克?
- volatile本質(zhì)是在告訴jvm當(dāng)前變量在寄存器(工作內(nèi)存)中的值是不確定的,需要從主存中讀惹捌铡肚邢; synchronized則是鎖定當(dāng)前變量,只有當(dāng)前線(xiàn)程可以訪(fǎng)問(wèn)該變量拭卿,其他線(xiàn)程被阻塞住骡湖。
- volatile僅能使用在變量級(jí)別;synchronized則可以使用在變量峻厚、方法响蕴、和類(lèi)級(jí)別的。
- volatile僅能實(shí)現(xiàn)變量的修改可見(jiàn)性惠桃,不能保證原子性浦夷;而synchronized則可以保證變量的修改可見(jiàn)性和原子性。
- volatile不會(huì)造成線(xiàn)程的阻塞刽射;synchronized可能會(huì)造成線(xiàn)程的阻塞军拟。
- volatile標(biāo)記的變量不會(huì)被編譯器優(yōu)化;synchronized標(biāo)記的變量可以被編譯器優(yōu)化誓禁。
54. synchronized 和 Lock 有什么區(qū)別懈息?
- 首先synchronized是java內(nèi)置關(guān)鍵字,在jvm層面摹恰,Lock是個(gè)java類(lèi)辫继;
- synchronized無(wú)法判斷是否獲取鎖的狀態(tài)怒见,Lock可以判斷是否獲取到鎖;
- synchronized會(huì)自動(dòng)釋放鎖(a 線(xiàn)程執(zhí)行完同步代碼會(huì)釋放鎖 姑宽;b 線(xiàn)程執(zhí)行過(guò)程中發(fā)生異常會(huì)釋放鎖)遣耍,Lock需在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成線(xiàn)程死鎖炮车;
- 用synchronized關(guān)鍵字的兩個(gè)線(xiàn)程1和線(xiàn)程2舵变,如果當(dāng)前線(xiàn)程1獲得鎖,線(xiàn)程2線(xiàn)程等待瘦穆。如果線(xiàn)程1阻塞纪隙,線(xiàn)程2則會(huì)一直等待下去,而Lock鎖就不一定會(huì)等待下去扛或,如果嘗試獲取不到鎖绵咱,線(xiàn)程可以不用一直等待就結(jié)束了;
- synchronized的鎖可重入熙兔、不可中斷悲伶、非公平,而Lock鎖可重入住涉、可判斷麸锉、可公平(兩者皆可);
- Lock鎖適合大量同步的代碼的同步問(wèn)題秆吵,synchronized鎖適合代碼少量的同步問(wèn)題淮椰。
55. synchronized 和 ReentrantLock 區(qū)別是什么?
synchronized是和if纳寂、else主穗、for、while一樣的關(guān)鍵字毙芜,ReentrantLock是類(lèi)忽媒,這是二者的本質(zhì)區(qū)別。既然ReentrantLock是類(lèi)腋粥,那么它就提供了比synchronized更多更靈活的特性晦雨,可以被繼承、可以有方法隘冲、可以有各種各樣的類(lèi)變量闹瞧,ReentrantLock比synchronized的擴(kuò)展性體現(xiàn)在幾點(diǎn)上:
- ReentrantLock可以對(duì)獲取鎖的等待時(shí)間進(jìn)行設(shè)置,這樣就避免了死鎖
- ReentrantLock可以獲取各種鎖的信息
- ReentrantLock可以靈活地實(shí)現(xiàn)多路通知
另外展辞,二者的鎖機(jī)制其實(shí)也是不一樣的:ReentrantLock底層調(diào)用的是Unsafe的park方法加鎖奥邮,synchronized操作的應(yīng)該是對(duì)象頭中mark word。
56. 說(shuō)一下 atomic 的原理?
- Atomic包中的類(lèi)基本的特性就是在多線(xiàn)程環(huán)境下洽腺,當(dāng)有多個(gè)線(xiàn)程同時(shí)對(duì)單個(gè)(包括基本類(lèi)型及引用類(lèi)型)變量進(jìn)行操作時(shí)脚粟,具有排他性,即當(dāng)多個(gè)線(xiàn)程同時(shí)對(duì)該變量的值進(jìn)行更新時(shí)蘸朋,僅有一個(gè)線(xiàn)程能成功核无,而未成功的線(xiàn)程可以向自旋鎖一樣,繼續(xù)嘗試藕坯,一直等到執(zhí)行成功团南。
- Atomic系列的類(lèi)中的核心方法都會(huì)調(diào)用unsafe類(lèi)中的幾個(gè)本地方法。我們需要先知道一個(gè)東西就是Unsafe類(lèi)堕担,全名為:sun.misc.Unsafe已慢,這個(gè)類(lèi)包含了大量的對(duì)C代碼的操作曲聂,包括很多直接內(nèi)存分配以及原子操作的調(diào)用霹购,而它之所以標(biāo)記為非安全的,是告訴你這個(gè)里面大量的方法調(diào)用都會(huì)存在安全隱患朋腋,需要小心使用齐疙,否則會(huì)導(dǎo)致嚴(yán)重的后果,例如在通過(guò)unsafe分配內(nèi)存的時(shí)候旭咽,如果自己指定某些區(qū)域可能會(huì)導(dǎo)致一些類(lèi)似C++一樣的指針越界到其他進(jìn)程的問(wèn)題贞奋。