欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java多線程與并發(fā)面試題(小結(jié))

  發(fā)布時(shí)間:2019-09-26 16:26:28   作者:Java知音_   我要評(píng)論
這篇文章主要介紹了Java多線程與并發(fā)面試題(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

1,什么是線程?

線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位,它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。程序員可以通過(guò)它進(jìn)行多處理器編程,你可以使用多線程對(duì)運(yùn)算密集型任務(wù)提速。比如,如果一個(gè)線程完成一個(gè)任務(wù)要100毫秒,那么用十個(gè)線程完成改任務(wù)只需10毫秒。

2,線程和進(jìn)程有什么區(qū)別?

線程是進(jìn)程的子集,一個(gè)進(jìn)程可以有很多線程,每條線程并行執(zhí)行不同的任務(wù)。不同的進(jìn)程使用不同的內(nèi)存空間,而所有的線程共享一片相同的內(nèi)存空間。每個(gè)線程都擁有單獨(dú)的棧內(nèi)存用來(lái)存儲(chǔ)本地?cái)?shù)據(jù)。

3,如何在Java中實(shí)現(xiàn)線程?

兩種方式:java.lang.Thread 類的實(shí)例就是一個(gè)線程但是它需要調(diào)用java.lang.Runnable接口來(lái)執(zhí)行,由于線程類本身就是調(diào)用的Runnable接口所以你可以繼承java.lang.Thread 類或者直接調(diào)用Runnable接口來(lái)重寫run()方法實(shí)現(xiàn)線程。

4,Java 關(guān)鍵字volatile 與 synchronized 作用與區(qū)別?

1,volatile它所修飾的變量不保留拷貝,直接訪問(wèn)主內(nèi)存中的。
在Java內(nèi)存模型中,有main memory,每個(gè)線程也有自己的memory (例如寄存器)。為了性能,一個(gè)線程會(huì)在自己的memory中保持要訪問(wèn)的變量的副本。這樣就會(huì)出現(xiàn)同一個(gè)變 量在某個(gè)瞬間,在一個(gè)線程的memory中的值可能與另外一個(gè)線程memory中的值,或者main memory中的值不一致的情況。 一個(gè)變量聲明為volatile,就意味著這個(gè)變量是隨時(shí)會(huì)被其他線程修改的,因此不能將它c(diǎn)ache在線程memory中。
2,synchronized

當(dāng)它用來(lái)修飾一個(gè)方法或者一個(gè)代碼塊的時(shí)候,能夠保證在同一時(shí)刻最多只有一個(gè)線程執(zhí)行該段代碼。

一、當(dāng)兩個(gè)并發(fā)線程訪問(wèn)同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。

二、然而,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問(wèn)該object中的非synchronized(this)同步代碼塊。

三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問(wèn)將被阻塞。

四、當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),它就獲得了這個(gè)object的對(duì)象鎖。結(jié)果,其它線程對(duì)該object對(duì)象所有同步代碼部分的訪問(wèn)都被暫時(shí)阻塞。

五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用.

5,有哪些不同的線程生命周期?

當(dāng)我們?cè)贘ava程序中新建一個(gè)線程時(shí),它的狀態(tài)是New。當(dāng)我們調(diào)用線程的start()方法時(shí),狀態(tài)被改變?yōu)镽unnable。線程調(diào)度器會(huì)為Runnable線程池中的線程分配CPU時(shí)間并且講它們的狀態(tài)改變?yōu)镽unning。其他的線程狀態(tài)還有Waiting,Blocked 和Dead。

6,你對(duì)線程優(yōu)先級(jí)的理解是什么?

每一個(gè)線程都是有優(yōu)先級(jí)的,一般來(lái)說(shuō),高優(yōu)先級(jí)的線程在運(yùn)行時(shí)會(huì)具有優(yōu)先權(quán),但這依賴于線程調(diào)度的實(shí)現(xiàn),這個(gè)實(shí)現(xiàn)是和操作系統(tǒng)相關(guān)的(OS dependent)。我們可以定義線程的優(yōu)先級(jí),但是這并不能保證高優(yōu)先級(jí)的線程會(huì)在低優(yōu)先級(jí)的線程前執(zhí)行。線程優(yōu)先級(jí)是一個(gè)int變量(從1-10),1代表最低優(yōu)先級(jí),10代表最高優(yōu)先級(jí)。

7,什么是死鎖(Deadlock)?如何分析和避免死鎖?

死鎖是指兩個(gè)以上的線程永遠(yuǎn)阻塞的情況,這種情況產(chǎn)生至少需要兩個(gè)以上的線程和兩個(gè)以上的資源。

分析死鎖,我們需要查看Java應(yīng)用程序的線程轉(zhuǎn)儲(chǔ)。我們需要找出那些狀態(tài)為BLOCKED的線程和他們等待的資源。每個(gè)資源都有一個(gè)唯一的id,用這個(gè)id我們可以找出哪些線程已經(jīng)擁有了它的對(duì)象鎖。

避免嵌套鎖,只在需要的地方使用鎖和避免無(wú)限期等待是避免死鎖的通常辦法。

8,什么是線程安全?Vector是一個(gè)線程安全類嗎? 

如果你的代碼所在的進(jìn)程中有多個(gè)線程在同時(shí)運(yùn)行,而這些線程可能會(huì)同時(shí)運(yùn)行這段代碼。如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。一個(gè)線程安全的計(jì)數(shù)器類的同一個(gè)實(shí)例對(duì)象在被多個(gè)線程使用的情況下也不會(huì)出現(xiàn)計(jì)算失誤。很顯然你可以將集合類分成兩組,線程安全和非線程安全的。Vector 是用同步方法來(lái)實(shí)現(xiàn)線程安全的, 而和它相似的ArrayList不是線程安全的。

9,Java中如何停止一個(gè)線程?

Java提供了很豐富的API但沒(méi)有為停止線程提供API。JDK 1.0本來(lái)有一些像stop(), suspend() 和 resume()的控制方法但是由于潛在的死鎖威脅因此在后續(xù)的JDK版本中他們被棄用了,之后Java API的設(shè)計(jì)者就沒(méi)有提供一個(gè)兼容且線程安全的方法來(lái)停止一個(gè)線程。當(dāng)run() 或者 call() 方法執(zhí)行完的時(shí)候線程會(huì)自動(dòng)結(jié)束,如果要手動(dòng)結(jié)束一個(gè)線程,你可以用volatile 布爾變量來(lái)退出run()方法的循環(huán)或者是取消任務(wù)來(lái)中斷線程

10,什么是ThreadLocal?

ThreadLocal用于創(chuàng)建線程的本地變量,我們知道一個(gè)對(duì)象的所有線程會(huì)共享它的全局變量,所以這些變量不是線程安全的,我們可以使用同步技術(shù)。但是當(dāng)我們不想使用同步的時(shí)候,我們可以選擇ThreadLocal變量。

每個(gè)線程都會(huì)擁有他們自己的Thread變量,它們可以使用get()\set()方法去獲取他們的默認(rèn)值或者在線程內(nèi)部改變他們的值。ThreadLocal實(shí)例通常是希望它們同線程狀態(tài)關(guān)聯(lián)起來(lái)是private static屬性。

11,Sleep()、suspend()和wait()之間有什么區(qū)別?

Thread.sleep()使當(dāng)前線程在指定的時(shí)間處于“非運(yùn)行”(Not Runnable)狀態(tài)。線程一直持有對(duì)象的監(jiān)視器。比如一個(gè)線程當(dāng)前在一個(gè)同步塊或同步方法中,其它線程不能進(jìn)入該塊或方法中。如果另一線程調(diào)用了interrupt()方法,它將喚醒那個(gè)“睡眠的”線程。

注意:sleep()是一個(gè)靜態(tài)方法。這意味著只對(duì)當(dāng)前線程有效,一個(gè)常見(jiàn)的錯(cuò)誤是調(diào)用t.sleep(),(這里的t是一個(gè)不同于當(dāng)前線程的線程)。即便是執(zhí)行t.sleep(),也是當(dāng)前線程進(jìn)入睡眠,而不是t線程。t.suspend()是過(guò)時(shí)的方法,使用suspend()導(dǎo)致線程進(jìn)入停滯狀態(tài),該線程會(huì)一直持有對(duì)象的監(jiān)視器,suspend()容易引起死鎖問(wèn)題。

object.wait()使當(dāng)前線程出于“不可運(yùn)行”狀態(tài),和sleep()不同的是wait是object的方法而不是thread。調(diào)用object.wait()時(shí),線程先要獲取這個(gè)對(duì)象的對(duì)象鎖,當(dāng)前線程必須在鎖對(duì)象保持同步,把當(dāng)前線程添加到等待隊(duì)列中,隨后另一線程可以同步同一個(gè)對(duì)象鎖來(lái)調(diào)用object.notify(),這樣將喚醒原來(lái)等待中的線程,然后釋放該鎖?;旧蟱ait()/notify()與sleep()/interrupt()類似,只是前者需要獲取對(duì)象鎖。

12,什么是線程餓死,什么是活鎖?

當(dāng)所有線程阻塞,或者由于需要的資源無(wú)效而不能處理,不存在非阻塞線程使資源可用。JavaAPI中線程活鎖可能發(fā)生在以下情形:

1,當(dāng)所有線程在程序中執(zhí)行Object.wait(0),參數(shù)為0的wait方法。程序?qū)l(fā)生活鎖直到在相應(yīng)的對(duì)象上有線程調(diào)用Object.notify()或者Object.notifyAll()。

2,當(dāng)所有線程卡在無(wú)限循環(huán)中。

13,什么是Java Timer類?如何創(chuàng)建一個(gè)有特定時(shí)間間隔的任務(wù)?

java.util.Timer是一個(gè)工具類,可以用于安排一個(gè)線程在未來(lái)的某個(gè)特定時(shí)間執(zhí)行。Timer類可以用安排一次性任務(wù)或者周期任務(wù)。

java.util.TimerTask是一個(gè)實(shí)現(xiàn)了Runnable接口的抽象類,我們需要去繼承這個(gè)類來(lái)創(chuàng)建我們自己的定時(shí)任務(wù)并使用Timer去安排它的執(zhí)行。

14,Java中的同步集合與并發(fā)集合有什么區(qū)別?

同步集合與并發(fā)集合都為多線程和并發(fā)提供了合適的線程安全的集合,不過(guò)并發(fā)集合的可擴(kuò)展性更高。

在Java1.5之前程序員們只有同步集合來(lái)用且在多線程并發(fā)的時(shí)候會(huì)導(dǎo)致?tīng)?zhēng)用,阻礙了系統(tǒng)的擴(kuò)展性。

Java5介紹了并發(fā)集合像ConcurrentHashMap,不僅提供線程安全還用鎖分離和    內(nèi)部分區(qū)等現(xiàn)代技術(shù)提高了可擴(kuò)展性。

15,同步方法和同步塊,哪個(gè)是更好的選擇?

同步塊是更好的選擇,因?yàn)樗粫?huì)鎖住整個(gè)對(duì)象(當(dāng)然你也可以讓它鎖住整個(gè)對(duì)象)。同步方法會(huì)鎖住整個(gè)對(duì)象,哪怕這個(gè)類中有多個(gè)不相關(guān)聯(lián)的同步塊,這通常會(huì)導(dǎo)致他們停止執(zhí)行并需要等待獲得這個(gè)對(duì)象上的鎖。

16,什么是線程池? 為什么要使用它?

創(chuàng)建線程要花費(fèi)昂貴的資源和時(shí)間,如果任務(wù)來(lái)了才創(chuàng)建線程那么響應(yīng)時(shí)間會(huì)變長(zhǎng),而且一個(gè)進(jìn)程能創(chuàng)建的線程數(shù)有限。

為了避免這些問(wèn)題,在程序啟動(dòng)的時(shí)候就創(chuàng)建若干線程來(lái)響應(yīng)處理,它們被稱為線程池,里面的線程叫工作線程。

從JDK1.5開(kāi)始,Java API提供了Executor框架讓你可以創(chuàng)建不同的線程池。比如單線程池,每次處理一個(gè)任務(wù);數(shù)目固定的線程池或者是緩存線程池(一個(gè)適合很多生存期短的任務(wù)的程序的可擴(kuò)展線程池)。

17,Java中invokeAndWait 和 invokeLater有什么區(qū)別?

這兩個(gè)方法是Swing API 提供給Java開(kāi)發(fā)者用來(lái)從當(dāng)前線程而不是事件派發(fā)線程更新GUI組件用的。InvokeAndWait()同步更新GUI組件,比如一個(gè)進(jìn)度條,一旦進(jìn)度更新了,進(jìn)度條也要做出相應(yīng)改變。如果進(jìn)度被多個(gè)線程跟蹤,那么就調(diào)用invokeAndWait()方法請(qǐng)求事件派發(fā)線程對(duì)組件進(jìn)行相應(yīng)更新。而invokeLater()方法是異步調(diào)用更新組件的。

18,多線程中的忙循環(huán)是什么?

忙循環(huán)就是程序員用循環(huán)讓一個(gè)線程等待,不像傳統(tǒng)方法wait(), sleep() 或 yield() 它們都放棄了CPU控制,而忙循環(huán)不會(huì)放棄CPU,它就是在運(yùn)行一個(gè)空循環(huán)。這么做的目的是為了保留CPU緩存。

在多核系統(tǒng)中,一個(gè)等待線程醒來(lái)的時(shí)候可能會(huì)在另一個(gè)內(nèi)核運(yùn)行,這樣會(huì)重建緩存。為了避免重建緩存和減少等待重建的時(shí)間就可以使用它了。

19,Java內(nèi)存模型是什么?

Java內(nèi)存模型規(guī)定和指引Java程序在不同的內(nèi)存架構(gòu)、CPU和操作系統(tǒng)間有確定性地行為。它在多線程的情況下尤其重要。Java內(nèi)存模型對(duì)一個(gè)線程所做的變動(dòng)能被其它線程可見(jiàn)提供了保證,它們之間是先行發(fā)生關(guān)系。這個(gè)關(guān)系定義了一些規(guī)則讓程序員在并發(fā)編程時(shí)思路更清晰。比如,先行發(fā)生關(guān)系確保了:

線程內(nèi)的代碼能夠按先后順序執(zhí)行,這被稱為程序次序規(guī)則。

對(duì)于同一個(gè)鎖,一個(gè)解鎖操作一定要發(fā)生在時(shí)間上后發(fā)生的另一個(gè)鎖定操作之前,也叫做管程鎖定規(guī)則。

前一個(gè)對(duì)volatile的寫操作在后一個(gè)volatile的讀操作之前,也叫volatile變量規(guī)則。

一個(gè)線程內(nèi)的任何操作必需在這個(gè)線程的start()調(diào)用之后,也叫作線程啟動(dòng)規(guī)則。

一個(gè)線程的所有操作都會(huì)在線程終止之前,線程終止規(guī)則。

一個(gè)對(duì)象的終結(jié)操作必需在這個(gè)對(duì)象構(gòu)造完成之后,也叫對(duì)象終結(jié)規(guī)則。

可傳遞性

20,Java中interrupted 和isInterruptedd方法的區(qū)別?

interrupted() 和 isInterrupted()的主要區(qū)別是前者會(huì)將中斷狀態(tài)清除而后者不會(huì)。Java多線程的中斷機(jī)制是用內(nèi)部標(biāo)識(shí)來(lái)實(shí)現(xiàn)的,調(diào)用Thread.interrupt()來(lái)中斷一個(gè)線程就會(huì)設(shè)置中斷標(biāo)識(shí)為true。當(dāng)中斷線程調(diào)用靜態(tài)方法Thread.interrupted()來(lái)檢查中斷狀態(tài)時(shí),中斷狀態(tài)會(huì)被清零。

非靜態(tài)方法isInterrupted()用來(lái)查詢其它線程的中斷狀態(tài)且不會(huì)改變中斷狀態(tài)標(biāo)識(shí)。簡(jiǎn)單的說(shuō)就是任何拋出InterruptedException異常的方法都會(huì)將中斷狀態(tài)清零。無(wú)論如何,一個(gè)線程的中斷狀態(tài)都有可能被其它線程調(diào)用中斷來(lái)改變。

21,Java中的同步集合與并發(fā)集合有什么區(qū)別?

同步集合與并發(fā)集合都為多線程和并發(fā)提供了合適的線程安全的集合,不過(guò)并發(fā)集合的可擴(kuò)展性更高。在Java1.5之前程序員們只有同步集合來(lái)用且在多線程并發(fā)的時(shí)候會(huì)導(dǎo)致?tīng)?zhēng)用,阻礙了系統(tǒng)的擴(kuò)展性。Java5介紹了并發(fā)集合像ConcurrentHashMap,不僅提供線程安全還用鎖分離和內(nèi)部分區(qū)等現(xiàn)代技術(shù)提高了可擴(kuò)展性。

不管是同步集合還是并發(fā)集合他們都支持線程安全,他們之間主要的區(qū)別體現(xiàn)在性能和可擴(kuò)展性,還有他們?nèi)绾螌?shí)現(xiàn)的線程安全上。

同步HashMap, Hashtable, HashSet, Vector, ArrayList 相比他們并發(fā)的實(shí)現(xiàn)(ConcurrentHashMap, CopyOnWriteArrayList, CopyOnWriteHashSet)會(huì)慢得多。造成如此慢的主要原因是鎖, 同步集合會(huì)把整個(gè)Map或List鎖起來(lái),而并發(fā)集合不會(huì)。并發(fā)集合實(shí)現(xiàn)線程安全是通過(guò)使用先進(jìn)的和成熟的技術(shù)像鎖剝離。

比如ConcurrentHashMap 會(huì)把整個(gè)Map 劃分成幾個(gè)片段,只對(duì)相關(guān)的幾個(gè)片段上鎖,同時(shí)允許多線程訪問(wèn)其他未上鎖的片段。

同樣的,CopyOnWriteArrayList 允許多個(gè)線程以非同步的方式讀,當(dāng)有線程寫的時(shí)候它會(huì)將整個(gè)List復(fù)制一個(gè)副本給它。

如果在讀多寫少這種對(duì)并發(fā)集合有利的條件下使用并發(fā)集合,這會(huì)比使用同步集合更具有可伸縮性。

22,什么是線程池? 為什么要使用它?

創(chuàng)建線程要花費(fèi)昂貴的資源和時(shí)間,如果任務(wù)來(lái)了才創(chuàng)建線程那么響應(yīng)時(shí)間會(huì)變長(zhǎng),而且一個(gè)進(jìn)程能創(chuàng)建的線程數(shù)有限。為了避免這些問(wèn)題,在程序啟動(dòng)的時(shí)候就創(chuàng)建若干線程來(lái)響應(yīng)處理,它們被稱為線程池,里面的線程叫工作線程。從JDK1.5開(kāi)始,Java API提供了Executor框架讓你可以創(chuàng)建不同的線程池。比如單線程池,每次處理一個(gè)任務(wù);數(shù)目固定的線程池或者是緩存線程池(一個(gè)適合很多生存期短的任務(wù)的程序的可擴(kuò)展線程池)

線程池的作用,就是在調(diào)用線程的時(shí)候初始化一定數(shù)量的線程,有線程過(guò)來(lái)的時(shí)候,先檢測(cè)初始化的線程還有空的沒(méi)有,沒(méi)有就再看當(dāng)前運(yùn)行中的線程數(shù)是不是已經(jīng)達(dá)到了最大數(shù),如果沒(méi)有,就新分配一個(gè)線程去處理。

就像餐館中吃飯一樣,從里面叫一個(gè)服務(wù)員出來(lái);但如果已經(jīng)達(dá)到了最大數(shù),就相當(dāng)于服務(wù)員已經(jīng)用盡了,那沒(méi)得辦法,另外的線程就只有等了,直到有新的“服務(wù)員”為止。

線程池的優(yōu)點(diǎn)就是可以管理線程,有一個(gè)高度中樞,這樣程序才不會(huì)亂,保證系統(tǒng)不會(huì)因?yàn)榇罅康牟l(fā)而因?yàn)橘Y源不足掛掉。

23,Java中活鎖和死鎖有什么區(qū)別?

活鎖:一個(gè)線程通常會(huì)有會(huì)響應(yīng)其他線程的活動(dòng)。如果其他線程也會(huì)響應(yīng)另一個(gè)線程的活動(dòng),那么就有可能發(fā)生活鎖。同死鎖一樣,發(fā)生活鎖的線程無(wú)法繼續(xù)執(zhí)行。然而線程并沒(méi)有阻塞——他們?cè)诿τ陧憫?yīng)對(duì)方無(wú)法恢復(fù)工作。這就相當(dāng)于兩個(gè)在走廊相遇的人:甲向他自己的左邊靠想讓乙過(guò)去,而乙向他的右邊靠想讓甲過(guò)去??梢?jiàn)他們阻塞了對(duì)方。甲向他的右邊靠,而乙向他的左邊靠,他們還是阻塞了對(duì)方。

死鎖:兩個(gè)或更多線程阻塞著等待其它處于死鎖狀態(tài)的線程所持有的鎖。死鎖通常發(fā)生在多個(gè)線程同時(shí)但以不同的順序請(qǐng)求同一組鎖的時(shí)候,死鎖會(huì)讓你的程序掛起無(wú)法完成任務(wù)。

24,如何避免死鎖?

死鎖的發(fā)生必須滿足以下四個(gè)條件:

互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用。

請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。

不剝奪條件:進(jìn)程已獲得的資源,在末使用完之前,不能強(qiáng)行剝奪。

循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

三種用于避免死鎖的技術(shù):

加鎖順序(線程按照一定的順序加鎖)

加鎖時(shí)限(線程嘗試獲取鎖的時(shí)候加上一定的時(shí)限,超過(guò)時(shí)限則放棄對(duì)該鎖的請(qǐng)求,并釋放自己占有的鎖)

死鎖檢測(cè)

25,notify()和notifyAll()有什么區(qū)別?
1,notify()和notifyAll()都是Object對(duì)象用于通知處在等待該對(duì)象的線程的方法。
2,void notify(): 喚醒一個(gè)正在等待該對(duì)象的線程。
3,void notifyAll(): 喚醒所有正在等待該對(duì)象的線程。
兩者的最大區(qū)別在于:
notifyAll使所有原來(lái)在該對(duì)象上等待被notify的線程統(tǒng)統(tǒng)退出wait的狀態(tài),變成等待該對(duì)象上的鎖,一旦該對(duì)象被解鎖,他們就會(huì)去競(jìng)爭(zhēng)。

notify他只是選擇一個(gè)wait狀態(tài)線程進(jìn)行通知,并使它獲得該對(duì)象上的鎖,但不驚動(dòng)其他同樣在等待被該對(duì)象notify的線程們,當(dāng)?shù)谝粋€(gè)線程運(yùn)行完畢以后釋放對(duì)象上的鎖,此時(shí)如果該對(duì)象沒(méi)有再次使用notify語(yǔ)句,即便該對(duì)象已經(jīng)空閑,其他wait狀態(tài)等待的線程由于沒(méi)有得到該對(duì)象的通知,繼續(xù)處在wait狀態(tài),直到這個(gè)對(duì)象發(fā)出一個(gè)notify或notifyAll,它們等待的是被notify或notifyAll,而不是鎖。

26,什么是可重入鎖(ReentrantLock)? 

Java.util.concurrent.lock 中的 Lock 框架是鎖定的一個(gè)抽象,它允許把鎖定的實(shí)現(xiàn)作為Java 類,而不是作為語(yǔ)言的特性來(lái)實(shí)現(xiàn)。這就為L(zhǎng)ock 的多種實(shí)現(xiàn)留下了空間,各種實(shí)現(xiàn)可能有不同的調(diào)度算法、性能特性或者鎖定語(yǔ)義。            ReentrantLock 類實(shí)現(xiàn)了Lock ,它擁有與synchronized 相同的并發(fā)性和內(nèi)存語(yǔ)義,但是添加了類似鎖投票、定時(shí)鎖等候和可中斷鎖等候的一些特性。此外,它還提供了在激烈爭(zhēng)用情況下更佳的性能。(換句話說(shuō),當(dāng)許多線程都想訪問(wèn)共享資源時(shí),JVM可以花更少的時(shí)候來(lái)調(diào)度線程,把更多時(shí)間用在執(zhí)行線程上。)
Reentrant 鎖意味著什么呢?簡(jiǎn)單來(lái)說(shuō),它有一個(gè)與鎖相關(guān)的獲取計(jì)數(shù)器,如果擁有鎖的某個(gè)線程再次得到鎖,那么獲取計(jì)數(shù)器就加1,然后鎖需要被釋放兩次才能獲得真正釋放。這模仿了synchronized 的語(yǔ)義;如果線程進(jìn)入由線程已經(jīng)擁有的監(jiān)控器保護(hù)的synchronized 塊,就允許線程繼續(xù)進(jìn)行,當(dāng)線程退出第二個(gè)(或者后續(xù))synchronized塊的時(shí)候,不釋放鎖,只有線程退出它進(jìn)入的監(jiān)控器保護(hù)的第一個(gè)synchronized 塊時(shí),才釋放鎖。

27,讀寫鎖可以用于什么應(yīng)用場(chǎng)景?
讀寫鎖可以用于 “多讀少寫” 的場(chǎng)景,讀寫鎖支持多個(gè)讀操作并發(fā)執(zhí)行,寫操作只能由一個(gè)線程來(lái)操作
ReadWriteLock對(duì)向數(shù)據(jù)結(jié)構(gòu)相對(duì)不頻繁地寫入,但是有多個(gè)任務(wù)要經(jīng)常讀取這個(gè)數(shù)據(jù)結(jié)構(gòu)的這類情況進(jìn)行了優(yōu)化。ReadWriteLock使得你可以同時(shí)有多個(gè)讀取者,只要它們都不試圖寫入即可。如果寫鎖已經(jīng)被其他任務(wù)持有,那么任何讀取者都不能訪問(wèn),直至這個(gè)寫鎖被釋放為止。
ReadWriteLock 對(duì)程序性能的提高主要受制于如下幾個(gè)因素:
1,數(shù)據(jù)被讀取的頻率與被修改的頻率相比較的結(jié)果。
2,讀取和寫入的時(shí)間
3,有多少線程競(jìng)爭(zhēng)
4,是否在多處理機(jī)器上運(yùn)行

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論