<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試被問線程問題!然后就被虐了

          共 3287字,需瀏覽 7分鐘

           ·

          2021-12-19 12:02

          最近行情特別好,小編也投了簡歷去面試了一下,結(jié)果被虐了,阿里果然都喜歡問底層問題。之后找了點(diǎn)資料,大家一起學(xué)習(xí)下。

          一、線程安全等級

          之前的博客中已有所提及“線程安全”問題,一般我們常說某某類是線程安全的,某某是非線程安全的。其實線程安全并不是一個“非黑即白”單項選擇題。

          按照“線程安全”的安全程度由強(qiáng)到弱來排序,我們可以將java語言中各種操作共享的數(shù)據(jù)分為以下5類:不可變、絕對線程安全、相對線程安全、線程兼容和線程對立。

          1、不可變

          在java語言中,不可變的對象一定是線程安全的,無論是對象的方法實現(xiàn)還是方法的調(diào)用者,都不需要再采取任何的線程安全保障措施。如final關(guān)鍵字修飾的數(shù)據(jù)不可修改,可靠性最高。

          2、絕對線程安全

          絕對的線程安全完全滿足Brian GoetZ給出的線程安全的定義,這個定義其實是很嚴(yán)格的,一個類要達(dá)到“不管運(yùn)行時環(huán)境如何,調(diào)用者都不需要任何額外的同步措施”通常需要付出很大的代價。

          3、相對線程安全

          相對線程安全就是我們通常意義上所講的一個類是“線程安全”的。另外,多線程系列面試題和答案全部整理好了,微信搜索Java技術(shù)棧,在后臺發(fā)送:面試,可以在線閱讀。

          它需要保證對這個對象單獨(dú)的操作是線程安全的,我們在調(diào)用的時候不需要做額外的保障措施,但是對于一些特定順序的連續(xù)調(diào)用,就可能需要在調(diào)用端使用額外的同步手段來保證調(diào)用的正確性。

          在java語言中,大部分的線程安全類都屬于相對線程安全的,例如Vector、HashTable、Collections的synchronizedCollection()方法保證的集合。

          4、線程兼容

          線程兼容就是我們通常意義上所講的一個類不是線程安全的。

          線程兼容是指對象本身并不是線程安全的,但是可以通過在調(diào)用端正確地使用同步手段來保證對象在并發(fā)環(huán)境下可以安全地使用。Java API中大部分的類都是屬于線程兼容的。如與前面的Vector和HashTable相對應(yīng)的集合類ArrayList和HashMap等。

          5、線程對立

          線程對立是指無論調(diào)用端是否采取了同步錯誤,都無法在多線程環(huán)境中并發(fā)使用的代碼。由于java語言天生就具有多線程特性,線程對立這種排斥多線程的代碼是很少出現(xiàn)的。

          一個線程對立的例子是Thread類的supend()和resume()方法。如果有兩個線程同時持有一個線程對象,一個嘗試去中斷線程,另一個嘗試去恢復(fù)線程,如果并發(fā)進(jìn)行的話,無論調(diào)用時是否進(jìn)行了同步,目標(biāo)線程都有死鎖風(fēng)險。正因此如此,這兩個方法已經(jīng)被廢棄啦。

          二、線程安全的實現(xiàn)方法

          保證線程安全以是否需要同步手段分類,分為同步方案和無需同步方案。

          1、互斥同步

          互斥同步是最常見的一種并發(fā)正確性保障手段。同步是指在多線程并發(fā)訪問共享數(shù)據(jù)時,保證共享數(shù)據(jù)在同一時刻只被一個線程使用(同一時刻,只有一個線程在操作共享數(shù)據(jù))。

          而互斥是實現(xiàn)同步的一種手段,臨界區(qū)、互斥量和信號量都是主要的互斥實現(xiàn)方式。因此,在這4個字里面,互斥是因,同步是果;互斥是方法,同步是目的。

          在java中,最基本的互斥同步手段就是synchronized關(guān)鍵字,synchronized關(guān)鍵字編譯之后,會在同步塊的前后分別形成monitorenter和monitorexit這兩個字節(jié)碼質(zhì)量,這兩個字節(jié)碼指令都需要一個reference類型的參數(shù)來指明要鎖定和解鎖的對象。

          此外,ReentrantLock也是通過互斥來實現(xiàn)同步。在基本用法上,ReentrantLock與synchronized很相似,他們都具備一樣的線程重入特性。另外,多線程系列面試題和答案全部整理好了,微信搜索Java技術(shù)棧,在后臺發(fā)送:面試,可以在線閱讀。

          互斥同步最主要的問題就是進(jìn)行線程阻塞和喚醒所帶來的性能問題,因此這種同步也成為阻塞同步。從處理問題的方式上說,互斥同步屬于一種悲觀的并發(fā)策略,總是認(rèn)為只要不去做正確地同步措施(例如加鎖),那就肯定會出現(xiàn)問題,無論共享數(shù)據(jù)是否真的會出現(xiàn)競爭,它都要進(jìn)行加鎖。

          2、非阻塞同步

          隨著硬件指令集的發(fā)展,出現(xiàn)了基于沖突檢測的樂觀并發(fā)策略,通俗地說,就是先進(jìn)行操作,如果沒有其他線程爭用共享數(shù)據(jù),那操作就成功了;如果共享數(shù)據(jù)有爭用,產(chǎn)生了沖突,那就再采用其他的補(bǔ)償措施。(最常見的補(bǔ)償錯誤就是不斷地重試,直到成功為止),這種樂觀的并發(fā)策略的許多實現(xiàn)都不需要把線程掛起,因此這種同步操作稱為非阻塞同步。

          非阻塞的實現(xiàn)CAS(compareandswap):CAS指令需要有3個操作數(shù),分別是內(nèi)存地址(在java中理解為變量的內(nèi)存地址,用V表示)、舊的預(yù)期值(用A表示)和新值(用B表示)。

          CAS指令執(zhí)行時,CAS指令指令時,當(dāng)且僅當(dāng)V處的值符合舊預(yù)期值A(chǔ)時,處理器用B更新V處的值,否則它就不執(zhí)行更新,但是無論是否更新了V處的值,都會返回V的舊值,上述的處理過程是一個原子操作。

          ABA問題:因為CAS需要在操作值的時候檢查下值有沒有發(fā)生變化,如果沒有發(fā)生變化則更新,但是一個值原來是A,變成了B,又變成了A,那么使用CAS進(jìn)行檢查時會發(fā)現(xiàn)它的值沒有發(fā)生變化,但是實際上卻變化了。

          ABA問題的解決思路就是使用版本號。在變量前面追加版本號,每次變量更新的時候把版本號加一,那么A-B-A就變成了1A-2B-3C。JDK的atomic包里提供了一個類AtomicStampedReference來解決ABA問題。

          這個類的compareAndSet方法作用是首先檢查當(dāng)前引用是否等于預(yù)期引用,并且當(dāng)前標(biāo)志是否等于預(yù)期標(biāo)志,如果全部相等,則以原子方式將該引用和該標(biāo)志的值設(shè)置為給定的更新值。

          3、無需同步方案

          要保證線程安全,并不是一定就要進(jìn)行同步,兩者沒有因果關(guān)系。同步只是保證共享數(shù)據(jù)爭用時的正確性的手段,如果一個方法本來就不涉及共享數(shù)據(jù),那它自然就無需任何同步操作去保證正確性,因此會有一些代碼天生就是線程安全的。

          1)可重入代碼

          可重入代碼(ReentrantCode)也稱為純代碼(Pure Code),可以在代碼執(zhí)行的任何時刻中斷它,轉(zhuǎn)而去執(zhí)行另外一段代碼,而在控制權(quán)返回后,原來的程序不會出現(xiàn)任何錯誤。所有的可重入代碼都是線程安全的,但是并非所有的線程安全的代碼都是可重入的。

          可重入代碼的特點(diǎn)是不依賴存儲在堆上的數(shù)據(jù)和公用的系統(tǒng)資源、用到的狀態(tài)量都是由參數(shù)中傳入、不調(diào)用 非可重入的方法等。

          (類比:synchronized擁有鎖重入的功能,也就是在使用synchronized時,當(dāng)一個線程得到一個對象鎖后,再次請求此對象鎖時時可以再次得到該對象的鎖)

          2)線程本地存儲

          如果一段代碼中所需的數(shù)據(jù)必須與其他代碼共享,那就看看這些共享數(shù)據(jù)的代碼是否能保證在同一個線程中執(zhí)行?如果能保證,我們就可以把共享數(shù)據(jù)的可見范圍限制在同一個線程之內(nèi)。這樣無需同步也能保證線程之間不出現(xiàn)數(shù)據(jù)的爭用問題。

          符合這種特點(diǎn)的應(yīng)用并不少見,大部分使用消費(fèi)隊列的架構(gòu)模式(如“生產(chǎn)者-消費(fèi)者”模式)都會將產(chǎn)品的消費(fèi)過程盡量在一個線程中消費(fèi)完。

          其中最重要的一個應(yīng)用實例就是經(jīng)典的Web交互模型中的“一個請求對應(yīng)一個服務(wù)器線程(Thread-per-Request)”的處理方式,這種處理方式的廣泛應(yīng)用使得很多Web服務(wù)器應(yīng)用都可以使用線程本地存儲來解決線程安全問題。

          原文鏈接:https://blog.csdn.net/qq_26545305/article/details/79516610/

          版權(quán)聲明:本文為CSDN博主「LemmonTreelss」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

          ——————END——————

          歡迎關(guān)注“Java引導(dǎo)者”,我們分享最有價值的Java的干貨文章,助力您成為有思想的Java開發(fā)工程師!

          瀏覽 78
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美成人精品在线播放 | 国语对白视频 | 免费看一区二区三区A片 | 美女日B视频 | 色人人操|