1.? ThreadLocal(線程變量副本)?
Synchronized實現(xiàn)內(nèi)存共享,ThreadLocal為每個線程維護(hù)一個本地變量。
采用空間換時間,它用于線程間的數(shù)據(jù)隔離,為每一個使用該變量的線程提供一個副本,每個線程都可以獨(dú)立地改變自己的副本,而不會和其他線程的副本沖突。
ThreadLocal類中維護(hù)一個Map,用于存儲每一個線程的變量副本,Map中元素的鍵為線程對象,而值為對應(yīng)線程的變量副本。
ThreadLocal在Spring中發(fā)揮著巨大的作用,在管理Request作用域中的Bean、事務(wù)管理、任務(wù)調(diào)度、AOP等模塊都出現(xiàn)了它的身影。
Spring中絕大部分Bean都可以聲明成Singleton作用域,采用ThreadLocal進(jìn)行封裝,因此有狀態(tài)的Bean就能夠以singleton的方式在多線程中正常工作了。
友情鏈接:深入研究java.lang.ThreadLocal類
2. Synchronized關(guān)鍵字、Lock,并解釋它們之間的區(qū)別?
? ? ? ?Synchronized 與Lock都是可重入鎖,同一個線程再次進(jìn)入同步代碼的時候.可以使用自己已經(jīng)獲取到的鎖
? ? ? ?Synchronized是悲觀鎖機(jī)制,獨(dú)占鎖。而Locks.ReentrantLock是,每次不加鎖而是假設(shè)沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。 ReentrantLock適用場景
? ? ? ?某個線程在等待一個鎖的控制權(quán)的這段時間需要中斷
? ? ? ?需要分開處理一些wait-notify,ReentrantLock里面的Condition應(yīng)用,能夠控制notify哪個線程,鎖可以綁定多個條件。
? ? ? ?具有公平鎖功能,每個到來的線程都將排隊等候。
友情鏈接:?Synchronized關(guān)鍵字、Lock,并解釋它們之間的區(qū)別
3. fail-fast是什么?
? ? ? ? fail-fast機(jī)制是java集合(Collection)中的一種錯誤機(jī)制。當(dāng)多個線程對同一個集合的內(nèi)容進(jìn)行操作時,就可能會產(chǎn)生fail-fast事件。
? ? ? ? 例如:當(dāng)某一個線程A通過iterator去遍歷某集合的過程中,若該集合的內(nèi)容被其他線程所改變了;那么線程A訪問集合時,就會拋出ConcurrentModificationException異常,產(chǎn)生fail-fast事件
4. 聊聊happens-before?
? ? ? ?如果兩個操作之間具有happens-before 關(guān)系,那么前一個操作的結(jié)果就會對后面一個操作可見。
? ? ? ?1)程序順序規(guī)則:一個線程中的每個操作,happens- before 于該線程中的任意后續(xù)操作。
? ? ? ?2)監(jiān)視器鎖規(guī)則:對一個監(jiān)視器鎖的解鎖,happens- before 于隨后對這個監(jiān)視器鎖的加鎖。
? ? ? ?3)volatile變量規(guī)則:對一個volatile域的寫,happens- before于任意后續(xù)對這個volatile域的讀。
? ? ? ?4)傳遞性:如果A happens- before B,且B happens- before C,那么A happens- before C。
? ? ? ?5)線程啟動規(guī)則:Thread對象的start()方法happens- before于此線程的每一個動作。
5. Volatile和Synchronized四個不同點(diǎn)?
????????1)粒度不同,前者針對變量 ,后者鎖對象和類
????????2)syn阻塞,volatile線程不阻塞
????????3)syn保證三大特性,volatile不保證原子性
????????4)syn編譯器優(yōu)化,volatile不優(yōu)化 volatile具備兩種特性:
1.保證此變量對所有線程的可見性,指一條線程修改了這個變量的值,新值對于其他線程來說是可見的,但并不是多線程安全的。
2.禁止指令重排序優(yōu)化。
6. Volatile如何保證內(nèi)存可見性?
1.當(dāng)寫一個volatile變量時,JMM會把該線程對應(yīng)的本地內(nèi)存中的共享變量刷新到主內(nèi)存。
2.當(dāng)讀一個volatile變量時,JMM會把該線程對應(yīng)的本地內(nèi)存置為無效。線程接下來將從主內(nèi)存中讀取共享變量。
7.? 同步、異步、阻塞、非阻塞是什么?
同步:就是一個任務(wù)的完成需要依賴另外一個任務(wù),只有等待被依賴的任務(wù)完成后,依賴任務(wù)才能完成。
異步:不需要等待被依賴的任務(wù)完成,只是通知被依賴的任務(wù)要完成什么工作,只要自己任務(wù)完成了就算完成了,被依賴的任務(wù)是否完成會通知回來。(異步的特點(diǎn)就是通知)。 打電話和發(fā)短信來比喻同步和異步操作。
阻塞:CPU停下來等一個慢的操作完成以后,才會接著完成其他的工作。
非阻塞:非阻塞就是在這個慢的執(zhí)行時,CPU去做其他工作,等這個慢的完成后,CPU才會接著完成后續(xù)的操作。非阻塞會造成線程切換增加,增加CPU的使用時間能不能補(bǔ)償系統(tǒng)的切換成本需要考慮。
友情鏈接:Java并發(fā)編程之volatile關(guān)鍵字解析
8.??線程之間如何通信的?
? ? ? ? 線程的通信是指線程之間以何種機(jī)制來交換信息。在編程中,線程之間的通信機(jī)制有兩種,共享內(nèi)存和消息傳遞。
????????在共享內(nèi)存的并發(fā)模型里,線程之間共享程序的公共狀態(tài),線程之間通過寫-讀內(nèi)存中的公共狀態(tài)來隱式進(jìn)行通信,典型的共享內(nèi)存通信方式就是通過共享對象進(jìn)行通信。
????????在消息傳遞的并發(fā)模型里,線程之間沒有公共狀態(tài),線程之間必須通過明確的發(fā)送消息來顯式進(jìn)行通信,在java中典型的消息傳遞方式就是wait()和notify()。
9.? 線程間如何同步的?
? ? ? ? 同步是指程序用于控制不同線程之間操作發(fā)生相對順序的機(jī)制。
????????在共享內(nèi)存并發(fā)模型里,同步是顯式進(jìn)行的。程序員必須顯式指定某個方法或某段代碼需要在線程之間互斥執(zhí)行。
????????在消息傳遞的并發(fā)模型里,由于消息的發(fā)送必須在消息的接收之前,因此同步是隱式進(jìn)行的。
10. 談?wù)剺酚^鎖與悲觀鎖?
悲觀鎖:
????????總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會阻塞直到它拿到鎖(共享資源每次只給一個線程使用,其它線程阻塞,用完后再把資源轉(zhuǎn)讓給其它線程)。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨(dú)占鎖就是悲觀鎖思想的實現(xiàn)。
樂觀鎖:
????????總是假設(shè)最好的情況,每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號機(jī)制和CAS算法實現(xiàn)。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫提供的類似于write_condition機(jī)制,其實都是提供的樂觀鎖。在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現(xiàn)方式CAS實現(xiàn)的。
11. 兩種鎖的使用場景?
? ? ? 從上面對兩種鎖的介紹,我們知道兩種鎖各有優(yōu)缺點(diǎn),不可認(rèn)為一種好于另一種,像樂觀鎖適用于寫比較少的情況下(多讀場景),即沖突真的很少發(fā)生的時候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個吞吐量。但如果是多寫的情況,一般會經(jīng)常產(chǎn)生沖突,這就會導(dǎo)致上層應(yīng)用會不斷的進(jìn)行retry,這樣反倒是降低了性能,所以一般多寫的場景下用悲觀鎖就比較合適。
12.?線程池有什么作用?
????????在程序啟動的時候就創(chuàng)建若干線程來響應(yīng)處理,它們被稱為線程池,里面的線程叫工作線程
????????第一:降低資源消耗。通過重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗。
????????第二:提高響應(yīng)速度。當(dāng)任務(wù)到達(dá)時,任務(wù)可以不需要等到線程創(chuàng)建就能立即執(zhí)行。
????????第三:提高線程的可管理性。
13. 常用線程池有哪些?:
????????ExecutorService 是主要的實現(xiàn)類,其中常用的有 ???????
?????????1)newCachedThreadPool創(chuàng)建一個可緩存線程池程
? ? ? ? ?2)newFixedThreadPool 創(chuàng)建一個定長線程池
? ? ? ? ?3)newScheduledThreadPool 創(chuàng)建一個線程池,它可安排在給定延遲后運(yùn)行命令或者定期地執(zhí)行
? ? ? ? ?4)newSingleThreadExecutor 創(chuàng)建一個單線程化的線程池
14. 線程池的優(yōu)點(diǎn)?
????????1)重用線程池的線程,避免因為線程的創(chuàng)建和銷毀鎖帶來的性能開銷
????????2)有效控制線程池的最大并發(fā)數(shù),避免大量的線程之間因搶占系統(tǒng)資源而阻塞
????????3)能夠?qū)€程進(jìn)行簡單的管理,并提供一下特定的操作如:可以提供定時、定期、單線程、并發(fā)數(shù)控制等功能
15.?同步方法和非同步方法可以同時調(diào)用?
????????可以的
16.? 對寫方法加鎖,對讀方法不加鎖,可以嗎?
? ? ? ? 容易產(chǎn)生臟讀
17.? 一個同步方法可以調(diào)用另一個同步方法嗎?
? ? ? ? 可以,一個線程已擁有某個對象的鎖,再次申請的時候仍然會得到該對象的鎖,也是說synchronized獲得的鎖是可重入的。
18. 程序處理中,被鎖定方法遇到異常,會怎么樣?
????????默認(rèn)情況下鎖會被釋放,所以并發(fā)處理過程中,有異常要多加小心,不然可能會發(fā)生不一致的情況。
比如,在一個web app處理過程中,多個servlet線程共同訪問同一個資源,這時如果異常處理不合適,在第一個線程中拋出異常,其他線程就會進(jìn)入同步打碼塊,有可能訪問到異常數(shù)據(jù)。
19.?volatile和synchronized的區(qū)別?
????????volatile本質(zhì)是在告訴jvm當(dāng)前變量在寄存器(工作內(nèi)存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當(dāng)前變量,只有當(dāng)前線程可以訪問該變量,其他線程被阻塞住。
????????volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
????????volatile僅能實現(xiàn)變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性
????????volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
????????volatile標(biāo)記的變量不會被編譯器優(yōu)化;synchronized標(biāo)記的變量可以被編譯器優(yōu)化。
20.?synchroized關(guān)鍵字,鎖什么地方?
????????synchroized鎖的是java堆內(nèi)存中的對某個對象,不是棧中的引用