九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項超值服

開通VIP
Java并發(fā)學(xué)習(xí)2【面試+工作】


Java并發(fā)學(xué)習(xí)2【面試+工作】

三.synchronized&volatile

synchronized

??關(guān)鍵字synchronized的作用是實現(xiàn)進(jìn)程間的同步。它的工作是對同步的代碼加鎖,使得每一次,只能有一個線程進(jìn)入同步塊,從而保證線程間的安全性(即同步塊每次應(yīng)該只有一個線程可以執(zhí)行)。

??關(guān)鍵字synchronized可以有多重用法,這里做一個簡單的整理。

  • 制定加鎖對象(同一對象)。對給定對象加鎖,進(jìn)入同步代碼前需要獲得給定對象的鎖。

  • 直接作用于實例方法。相當(dāng)于對當(dāng)前示例加鎖(同一對象),進(jìn)入同步代碼前要獲得當(dāng)前示例的鎖。

  • 直接作用于靜態(tài)方法。相當(dāng)于對當(dāng)前類加鎖,進(jìn)入同步代碼前要獲得當(dāng)前類的鎖。

??學(xué)習(xí)過《操作系統(tǒng)》的,這里非常容易理解,不在舉具體的例子。

??除了用于線程同步、確保線程安全外,synchronized還可以保證線程間的可見性和有序性。從可見性的角度講,synchronized可以完全替代volatile的功能,只是使用上沒有那么方便而已。就有序性而言,被synchronized限制的多線程其實是串行的執(zhí)行同步代碼的。

volatile

??用一句話概括volatile,它能夠使變量在值發(fā)生改變時能盡快地讓其他線程知道.

??首先我們要先意識到有這樣的現(xiàn)象,編譯器為了加快程序運(yùn)行的速度,對一些變量的寫操作會先在寄存器或者是CPU緩存上進(jìn)行,最后才寫入內(nèi)存. 
而在這個過程,變量的新值對其他線程是不可見的.而volatile的作用就是使它修飾的變量的讀寫操作都必須在內(nèi)存中進(jìn)行!

volatile與synchronized

  • volatile本質(zhì)是在告訴jvm當(dāng)前變量在寄存器中的值是不確定的,需要從主存中讀取,synchronized則是鎖定當(dāng)前變量,只有當(dāng)前線程可以訪問該變量,其他線程被阻塞住.

  • volatile僅能使用在變量級別,synchronized則可以使用在變量,方法.

  • volatile僅能實現(xiàn)變量的修改可見性,但不具備原子特性,而synchronized則可以保證變量的修改可見性和原子性.

  • volatile不會造成線程的阻塞,而synchronized可能會造成線程的阻塞.

  • volatile標(biāo)記的變量不會被編譯器優(yōu)化,而synchronized標(biāo)記的變量可以被編譯器優(yōu)化.

??因此,在使用volatile關(guān)鍵字時要慎重,并不是只要簡單類型變量使用volatile修飾,對這個變量的所有操作都是原來操作,當(dāng)變量的值由自身的上一個決定時,如n=n+1、n++ 等,volatile關(guān)鍵字將失效,只有當(dāng)變量的值和自身上一個值無關(guān)時對該變量的操作才是原子級別的,如n = m + 1,這個就是原級別的。所以在使用volatile關(guān)鍵時一定要謹(jǐn)慎,如果自己沒有把握,可以使用synchronized來代替volatile。

??總結(jié):volatile本質(zhì)是在告訴JVM當(dāng)前變量在寄存器中的值是不確定的,需要從主存中讀取??梢詫崿F(xiàn)synchronized的部分效果,但當(dāng)n=n+1,n++等時,volatile關(guān)鍵字將失效,不能起到像synchronized一樣的線程同步的效果


四.重入鎖&Condition條件

重入鎖

??這里介紹一下synchronized、wait、notify方法的替代品(或者說是增強(qiáng)版)-重入鎖。重入鎖是可以完全替代以上的內(nèi)容的。并且重入鎖的性能是遠(yuǎn)高于synchronized的,但是jdk6.0開始,jdk對synchronized做了大量的優(yōu)化,使得兩者性能差距不大。

??重入鎖使用java.util.concurrent.locks.ReentrantLock類來實現(xiàn)。它的幾個重要方法如下:

注意:把解鎖操作lock.unlock()放到finally子句非常重要。這樣保證即使在臨界區(qū)的代碼拋出了異常,鎖也必須釋放,否則,其他線程將永遠(yuǎn)阻塞.

重入鎖簡單案例: lock與unLock

??上述代碼使用重入鎖保護(hù)臨界區(qū)資源i,確保了多線程對i操作的安全性。從這段代碼可以看到,與synchronized相比,重入鎖有著顯示的操作過程。開發(fā)人員必須手動指定何時加鎖,何時釋放鎖。也正因為這樣,重入鎖對邏輯控制的靈活性要遠(yuǎn)遠(yuǎn)好于synchronized,但值得注意的是,在提出臨界區(qū)時,必須記得釋放鎖,否則其他線程就沒有機(jī)會再訪問臨界區(qū)了。

??對于重入鎖,同一個線程可以多次獲得鎖,但是釋放鎖的時候,也必須釋放相同次數(shù)。否則會產(chǎn)生異常。

重入鎖的中斷響應(yīng):lockInterruptibly

鎖申請等待限時:lock.tryLock的兩個方法

公平鎖:ReentrantLock的構(gòu)造函數(shù)可以增加一個參數(shù)

Condition條件

??如果大家理解了obj.wait和obj.notify方法的話,那么就很容易理解Condition對象了。它和wait和notify方法的作用是大致相同的。但是wait和notify方法是和synchronized關(guān)鍵字合作使用的,而Condition是與重入鎖相關(guān)聯(lián)的。通過Condition的newCondition()方法可以生成一個與當(dāng)前重入鎖綁定的Condition實例。利用Condition對象,我們就可以讓線程在合適的時間等待,或者在某一個特定的時間得到通知,繼續(xù)執(zhí)行。

Condition提供的基本方法如下:

以上方法的具體含義如下:

  • await() 方法會是當(dāng)前線程等待,同時釋放當(dāng)前鎖,當(dāng)其他線程中使用signal() 或signalAll() 方法時,線程會重新獲得鎖并繼續(xù)執(zhí)行。或者當(dāng)線程被中斷時,也能跳出等待。這和obj.wait方法很相似。

  • awaitUninterruptibly() 方法與await() 方法基本相同,只不過它不會在等待過程中響應(yīng)中斷。

  • signal() 方法用于喚醒一個在等待中的線程,這和obj.notify方法很類似。

簡單示例

??代碼中,聽過lock生成一個與之綁定的Condition對象。代碼15行要求線程在Condition對象上進(jìn)行等待。代碼32行,由主線程發(fā)起通知,告知等待在Condition上的線程可以繼續(xù)執(zhí)行了。

??和obj.wait和notify方法一樣,當(dāng)線程使用Condition.await時,要求線程持有相關(guān)的重入鎖,在Condition.await調(diào)用后,這個線程會釋放這把鎖。同理,在Condition.signal方法調(diào)用時,也要求線程先獲得相關(guān)的鎖。在signal方法調(diào)用后,系統(tǒng)會從當(dāng)前Condition對象的等待隊列中,喚醒一個線程。一旦線程被喚醒,它會重新嘗試獲得與之綁定的重入鎖,一旦成功獲取,就可以繼續(xù)執(zhí)行了。因此,在signal方法調(diào)用之后,一般需要釋放相關(guān)的鎖,謙讓給被喚醒的線程,讓他可以繼續(xù)執(zhí)行。比如,在本例中,第33行就釋放了重入鎖,如果省略第24行,那么,雖然已經(jīng)喚醒了線程t1,但是由于它無法重新獲得鎖,因而也就無法真正的繼續(xù)執(zhí)行。

??在jdk內(nèi)部,重入鎖和Condition對象被廣泛的使用,后面講到的線程安全的容器,他們的內(nèi)容時候都有重入鎖和Condition對象的影子。


五.信號量

信號量為多線程協(xié)作提供了更為強(qiáng)大的控制方法。廣義上說,信號量是對鎖的擴(kuò)展。無論是內(nèi)部鎖synchronized還是重入鎖ReentrantLock,一次都只允許一個線程訪問一個資源,而信號量卻可以指定多個線程,同時訪問某一個資源。信號量主要提供了一下構(gòu)造函數(shù):

??在構(gòu)造信號量對象時,必須要指定信號量的準(zhǔn)入數(shù),即同時能申請多少個許可。當(dāng)每個線程每次只申請一個許可時,這就相當(dāng)于指定了同時有多少個線程可以訪問某一個資源。信號量的主要邏輯方法有:

這里只講幾個常用的方法:

  • acquire() 方法嘗試獲得一個準(zhǔn)入的許可。若無法獲得,則線程會等待,直到有線程釋放一個許可或者當(dāng)前線程被中斷。

  • acquireUninterruptibly方法和acquire方法類似,但是不響應(yīng)中斷。

  • tryAcquire嘗試獲得一個許可,如果成功返回true,失敗返回false,它不會進(jìn)行等待,立即返回。

  • release用于在線程訪問資源結(jié)束后,釋放一個許可,以使其他等待許可的線程可以進(jìn)行資源訪問。

一個案例:

??上述代碼中,15、16行為臨界區(qū),程序會限制執(zhí)行這段代碼的線程數(shù)。這里在第7行,聲明了一個包含5個許可的信號量。這就意味著同時可以有5個線程進(jìn)入代碼段15,16行。申請信號量使用semp.acquire,在離開時,務(wù)必使用semp.release釋放信號量。這就和釋放鎖一個道理。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
『互聯(lián)網(wǎng)架構(gòu)』軟件架構(gòu)
多線程調(diào)優(yōu)經(jīng)驗-并發(fā)控制方法
面試終敗“高并發(fā)”,25天苦心鉆研,居然整出一份并發(fā)寶典?
java面試題 --- 并發(fā)②
轉(zhuǎn)載:從synchronized 到CAS 和 AQS徹底弄懂Java各種并發(fā)鎖
面經(jīng)手冊 · 第15篇《碼農(nóng)會鎖,synchronized 解毒,剖析源碼深度分析!》
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服