




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、java鎖的知識總結(jié)及實例代碼這篇文章主要介紹了 java鎖的知識總結(jié)及實例代碼,需要的朋友可以參考下java中有哪些鎖這個問題在我看了一遍vjava并發(fā)編程后盡然無法回答,說明自己對于鎖的概念了解的不 夠。于是再次翻看了一下書里的內(nèi)容,突然有點打開腦門的感覺??磥泶_實是要學(xué)習(xí)的最好 方式是要帶著問題去學(xué),并且解決問題。在java屮鎖主要兩類:內(nèi)部鎖synchronized和顯示鎖java.util.concurrent.locks.locko但細(xì)細(xì) 想這貌似總結(jié)的也不太對。應(yīng)該是由java內(nèi)置的鎖和concurrent實現(xiàn)的一系列鎖。為什么這說,因為在java中一切都是對象,而java對每個
2、對象都內(nèi)置了一個鎖,也可以稱 為對象鎖/內(nèi)部鎖。通過synchronized來完成相關(guān)的鎖操作。而因為synchronized的實現(xiàn)有些缺陷以及并發(fā)場景的復(fù)雜性,有人開發(fā)了一種顯式的鎖,而 這些鎖都是由java.util.concurrent.locks.lock派牛出來的。當(dāng)然目前己經(jīng)內(nèi)置到了 jdk1.5及之 后的版本中。syn chr on ized首先來看看用的比較多的synchronized,我的口常工作中大多用的也是它。synchronized是 用于為某個代碼塊的提供鎖機(jī)制,在java的對象中會隱式的擁有一個鎖,這個鎖被稱為內(nèi) 置鎖(intrinsic)或監(jiān)視器鎖(monitor
3、 locks)o線程在進(jìn)入被synchronized保護(hù)的塊z前自動獲得 這個鎖,直到完成代碼后(也可能是異常)自動釋放鎖。內(nèi)置鎖是互斥的,一個鎖同時只能被 一個線稈持有,這也就會導(dǎo)致多線程下,鎖被持有后后面的線程會阻塞。正因此實現(xiàn)了對代 碼的線程安全保證了原子性??芍厝爰热籮ava內(nèi)置鎖是互斥的而且后面的線程會導(dǎo)致阻塞,那么如杲持有鎖的線程再次進(jìn)入試 圖獲得這個鎖時會如何呢?比如下面的一種情況:public class baseclass public synchronized void do() system.out.println("is base"); public
4、 class sonclass exte nds baseclass public syn chronized void do() system.out.println("is son”); super.do(); sonclass son = new sonclass();son.do();此時派生類的do方法除了會首先會持有一次鎖,然后在調(diào)用super.dof)的時候又會再一次進(jìn) 入鎖并去持有,如果鎖是互斥的話此時就應(yīng)該死鎖了。但結(jié)果卻不是這樣的,這是因為內(nèi)部鎖是具有可重入的特性,也就是鎖實現(xiàn)了一個重入機(jī)制, 引用計數(shù)管理。當(dāng)線程1持有了對象的鎖a,此時會對鎖a的引用計算加1。然
5、后當(dāng)線程1 再次獲得鎖a時,線程1還是持有鎖a的那么計算會加1。當(dāng)然每次退出同步塊吋會減1, 直到為0吋釋放鎖。synchronized 的一些特點修飾代碼的方式修飾方法public class baseclass public synchronized void do() system.out.println(”is base"); 這種就是直接對某個方法進(jìn)行加鎖,進(jìn)入這個方法塊吋需要獲得鎖。修飾代碼塊public class baseclass private static object lock = new object(); public void do() synchron
6、ized (lock) system.out.println("is base"); 這里就將鎖的范圍減少到了方法中的部分代碼塊,這對于鎖的靈活性就提高了,畢竟鎖的粒 度控制也是鎖的一個關(guān)鍵問題。對彖鎖的類型經(jīng)??吹揭恍┐a中對synchronized使用比較特別,看一下如下的代碼:public class baseclass private static object lock = new object(); public void do() synchronized (lock) public synchronized void dovoid() publicsynch
7、ronized static void dostaticvoid() public static void dostaticvoid()synchronized (baseclass.class) 這里出現(xiàn)了四種情況:修飾代碼塊,修飾了方法,修飾了靜態(tài)方法,修飾baseclass的class 對象。那這幾種情況會有什么不同呢?修飾代碼塊這種情況下我們創(chuàng)建了一個對象lock,在代碼中使用synchronized(lock)這種形式,它的意思 是使用lock這個對象的內(nèi)置鎖。這種情況下就將鎖的控制交給了一個對象。當(dāng)然這種情況 還有一種方式:public void do() synchronized
8、 (this) system.out.println("is base"); 使用this的意思就是當(dāng)前對象的鎖。這里也道出了內(nèi)置鎖的關(guān)鍵,我提供一把鎖來保護(hù)這塊 代碼,無論哪個線程來都面對同一把鎖咯。修飾對象方法這種直接修飾在方法是咱個情況?其實和修飾代碼塊類似,只不過此時默認(rèn)使用的是this, 也就是當(dāng)前對象的鎖。這樣寫起代碼來倒也比較簡單明確。前面說過了與修飾代碼塊的區(qū)別 主要還是控制粒度的區(qū)別。修飾靜態(tài)方法靜態(tài)方法難道有啥不一樣嗎?確實是不一樣的,此時獲取的鎖已經(jīng)不是this 了,而this對象 指向的class,也就是類鎖。因為java中的類信息會加載到方法常量區(qū)
9、,全局是唯一的。這 其實就提供了一種全局的鎖。修飾類的class對象這種情況其實和修改靜態(tài)方法時比較類似,只不過還是一個道理這種方式可以提供更靈活的 控制粒度。小結(jié)通過這兒種情況的分析與理解,其實可以看內(nèi)置鎖的主要核心理念就是為一塊代碼提供一個 可以用于互斥的鎖,起到類似于開關(guān)的功能。java中對內(nèi)置鎖也提供了一些實現(xiàn),主要的特點就是java都是對象,而每個對象都有鎖,所 以可以根據(jù)情況選擇用什么樣的鎖。java.util.c on curre nto cks.lock前而看了 synchronized.大部分的情況下差不多就夠啦,但是現(xiàn)在系統(tǒng)在并發(fā)編程中復(fù)朵性 是越來越高,所以總是有許多場景
10、synchronized處理起來會比較費(fèi)勁?;蛘呦駐java并發(fā)編 程中說的那樣,concurrent中的lock是對內(nèi)部鎖的一種補(bǔ)充,提供了更多的一些高級特性。java.util.concurrentocks.lock 簡單分析這個接口抽象了鎖的主要操作,也因此讓從lock派生的鎖具備了這些基本的特性:無條件 的、可輪循的、定時的、可中斷的。而且加鎖與解鎖的操作都是顯式進(jìn)行。下面是它的代碼:public in terface lock void lock(); void lockl nterruptibly() throws in terruptedexception; boolean tr
11、ylock(); boolean trylock(long time, timellnit unit) throws interruptedexception; void unlock(); condition newcondition();ree ntran tlockreentrantlock就是可重入鎖,連名字都這么顯式。reentrantlock提供了和synchronized類似 的語義,但是reentrantlock必須顯式的調(diào)用,比如:public class baseclass private lock lock = new reentrantlock();public voi
12、d do()lock.lock(); try /. finally lock.unlockf); 這種方式對于代碼閱讀來說還是比較清楚的,只不過有個問題,就是如果忘了加try finally 或忘了寫lock.unlock()的話導(dǎo)致鎖沒釋放,很有可能導(dǎo)致一些死鎖的情況,synchronized就 沒有這個風(fēng)險。trylockreentrantlock是實現(xiàn)lock接口,所以自然就擁有它的那些特性,其中就有trylock« trylock 就是嘗試獲取鎖,如杲鎖已經(jīng)被其他線程占用那么立即返回false,如杲?jīng)]有那么應(yīng)該占用 它并返回true,表示拿到鎖啦。另一個trylock方法里帶
13、了參數(shù),這個方法的作用是指定一個時間,表示在這個時間內(nèi)一直 嘗試去獲得鎖,如果到時間還沒有拿到就放棄。因為trylock對鎖并不是一直阻塞等待的,所以可以更多的規(guī)避死鎖的發(fā)生。locklnterruptiblylocklnterruptibly是在線程獲取鎖時優(yōu)先響應(yīng)屮斷,如果檢測到中斷拋出中斷異常由上層代碼 去處理。這種情況下就為一種輪循的鎖提供了退出機(jī)制。為了更好理解可中斷的鎖操作,寫 了一個demo來理解。package com.test; import java.util.date;import java.util.concurrentocks.reentrantlock; publi
14、c class testlocklnterruptibly static reentrantlock lock = new reentrantlock(); public static void main(stri ng args) thread threadl = new thread (new runn able() override publicvoid run() try doprint("thread 1 get lock."); dol23(); doprint("thread 1 end.")/ catch (interruptedexce
15、ption e) doprint("thread 1 is interrupted."); );thread thread2 = new thread (new runn able() override public void run() try doprintf'thread 2 get lock."); dol23(); doprint("thread 2 end."); catch(interruptedexception e) dopri nt(”thread 2 is in terrupted."); );threa
16、dl.setname(hthreadl"); thread2.setname("thread2n); threadl.start(); try thread.sleep(loo);/ 等待一會使得 threadl 會在 thread2 前面執(zhí)行 catch (interruptedexception e) e.printstacktrace(); thread2.start(); private static void dol23() throwsin terruptedexcepti onlockockln terruptibly();doprint cthread.cu
17、rrentthread().getname()+"islocked.");try doprint(thread.currentthread().getname() + " dosomingl.thread.sleep(5000);/等待幾秒方便查看線程的先后順序 doprint(thread.currentthread().getname() + " dosoming2."); doprintcthread.currentthread().getname() + " is finished."); finally lock.
18、unlock); private static void doprint(string text) system.out.println(new date().tolocalestring() + " : " + text);上面代碼屮有兩個線程,threadl比thread2更早啟動,為了能看到拿鎖的過程將上鎖的代 碼sleep 7 5秒鐘,這樣就可以感受到前后兩個線程進(jìn)入獲取鎖的過程。最終上面的代碼運(yùn) 行結(jié)果如下:2016-9-28 15:12:56 : thread 1 get lock.2016-9-28 15:12:562016-9-28 15:12:562016
19、-9-28 15:12:562016-9-28 15:13:012016-9-28 15:13:012016-9-28 15:13:012016-9-28 15:13:012016-9-28 15:13:012016-9-28 15:13:012016-9-28 15:13:062016-9-28 15:13:062016-9-28 15:13:062016-9-28 15:13:06threadl is locked, threadl dosomingl. thread 2 get lock.threadl dosoming2. threadl is finished, threadl is
20、 unloaded. thread2 is locked.thread2 dosomingl. thread 1 end.thread2 dosoming2. thread2 is finished.thread2 is unloaded, thread 2 end.可以看到,threadl先獲得鎖,一會thread2也來拿鎖,但這個時候threadl己經(jīng)占用了,所 以thread2 一直到threadl釋放了鎖后才拿到鎖。*這段代碼說明locklnterruptibly后面來獲取鎖的線程需要等待前血的鎖釋放了才能獲得鎖。 和但這里還沒有體現(xiàn)出可中斷的待點,為此增加一些代碼:thread2.s
21、tart();try thread.sleep(1000); catch (interruptedexception e) e.printstacktrace(); /i 秒后把線程 2 中斷 errupt();在thread2啟動后調(diào)用一下thread2的中斷方法,好吧,先跑一下代碼看看結(jié)果:2016-9-28 15:16:46 : thread 1 get lock.2016-9-28 15:16:46 : threadl is locked.2016-9-28 15:16:46 : threadl dosomingl.2016-9-28 15:16:46 : thr
22、ead 2 get lock.2016-9-28 15:16:47 : thread 2 is interrupted. v-直接就響應(yīng)了線程中斷2016-9-28 15:16:51: threadl dosoming2.2016-9-28 15:16:51: threadl is finished.2016-9-28 15:16:51: threadl is unloaded.2016-9-28 15:16:51: thread 1 end.和前面的代碼相比可以發(fā)現(xiàn),thread2正在等待threadl釋放鎖,但是這時thread2自己中 斷了,thread2后面的代碼則不會再繼續(xù)執(zhí)行。re
23、adwritelock顧名思義就是讀寫鎖,這種讀寫鎖的應(yīng)用場景可以這樣理解,比如一波數(shù)據(jù)大部分時候都 是提供讀取的,而只有比較少量的寫操作,那么如果用互斥鎖的話就會導(dǎo)致線程間的鎖競爭。 如果對于讀取的吋候大家都可以讀,一旦要寫入的吋候就再將某個資源鎖住。這樣的變化就 很好的解決了這個問題,使的讀操作可以提高讀的性能,又不會影響寫的操作。一個資源可以被多個讀者訪問,或者被一個寫者訪問,兩者不能同時進(jìn)行。這是讀寫鎖的抽象接口,定義一個讀鎖和一個寫鎖。public interface readwritelock /* * returns the lock used for reading. * *
24、return the lock used for reading */ lock readlock(); /* * returns the lock used for writing.* return the lock used for writing */ lock writelock();在 jdk 里有個 reentrantreadwritelock 實現(xiàn),就是可重入的讀寫鎖。reentrantreadwritelock 可以構(gòu)造為公平的或者非公平的兩種類型。如果在構(gòu)造時不顯式指定則會默認(rèn)的創(chuàng)建非公平 鎖。在非公平鎖的模式下,線程訪問的順序是不確定的,就是可以闖入;可以由寫者降級為 讀者,但是讀者不能升級為寫者。如果是公平鎖模式,那么選擇權(quán)交給等待時間最長的線程,如果一個讀線程獲得鎖,此時一 個寫線程請求寫入鎖,那么就不再接收讀鎖的獲取,直到寫入操作完成。簡單的代碼分析 在reentrantreadwritelock里其實維護(hù)的是一個sync的鎖,只是看起來語 義上像是一個讀鎖和寫鎖??匆幌滤臉?gòu)造函數(shù):public reentrantreadwritelock(boolean fair) sync = fair ? new fairsync() : new nonfairsync(); readerlock = new readlock(this); w
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 代謝綜合征與衰老過程-全面剖析
- 農(nóng)村電商模式研究-全面剖析
- 交互設(shè)計的創(chuàng)新趨勢-全面剖析
- 客服行業(yè)區(qū)塊鏈技術(shù)應(yīng)用探索-全面剖析
- 即插即用技術(shù)的安全性評估-全面剖析
- 二維材料在水凈化技術(shù)中的應(yīng)用-全面剖析
- 反射孿生在虛擬仿真-全面剖析
- 勞動市場供需匹配-全面剖析
- 質(zhì)量管理部年度質(zhì)量控制計劃
- 2025年協(xié)同管理軟件項目合作計劃書
- 工程管理行業(yè)環(huán)境分析報告
- 《費(fèi)加羅的婚禮》序曲課件-高中音樂鑒賞
- 化學(xué)品MRSL培訓(xùn)教材
- 部編版小學(xué)語文二年級下冊第三單元集體備課教材分析
- 部編版《道德與法治》五年級下冊第7課《不甘屈辱 奮勇抗?fàn)帯方虒W(xué)課件
- 100道地理常識題全集
- 天津市和平區(qū)2023-2024學(xué)年九年級歷史下學(xué)期第一次質(zhì)量調(diào)查歷史試題
- 2024年版《安全生產(chǎn)法》
- 2024上海高考英語名校六選四試題真題匯編(含答案詳解)
- T-CRHA 028-2023 成人住院患者靜脈血栓栓塞癥風(fēng)險評估技術(shù)
- T-NAHIEM 98-2023 病理科(中心)建設(shè)與配置標(biāo)準(zhǔn)
評論
0/150
提交評論