99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

JAVA最好的加鎖方法是什么

汽車玩家 ? 來(lái)源:oschina ? 作者:oschina ? 2020-05-03 17:44 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

關(guān)于synchronized

眾所周知,JAVA中最簡(jiǎn)單的加鎖方法是用關(guān)鍵字synchronized,我們可以使用這個(gè)關(guān)鍵字將一個(gè)方法變成線程安全的,也可以將一個(gè)代碼塊變成線程安全的,這樣子我們不需要再擔(dān)心多線程同時(shí)執(zhí)行到這段代碼會(huì)引發(fā)的并發(fā)問(wèn)題。同時(shí)配合方法wait,notify和notifyall可以很好的實(shí)現(xiàn)多線程之間的協(xié)作,比如某個(gè)線程因?yàn)樾枰却恍┵Y源,于是調(diào)用wait方法將自己設(shè)置為waiting狀態(tài),其他線程釋放或生產(chǎn)這個(gè)線程需要的資源的時(shí)候需要通知這個(gè)線程(notify)將其喚醒,或者通知所有等待當(dāng)前資源的線程(notifyall)。

然而當(dāng)功能完成之后我們似乎并不滿足于此,于是我們開始考慮這么做的代價(jià)是什么,是否可以做的更好。

先說(shuō)說(shuō)這么做(使用synchronized)的代價(jià)是什么,當(dāng)多個(gè)線程請(qǐng)求臨界資源的時(shí)候只能有一個(gè)線程得到滿足,那么其他的線程會(huì)做什么呢,他們會(huì)被阻塞,直到被通知(notify/notifyall)又有資源的時(shí)候才被喚醒進(jìn)行再一次的鎖爭(zhēng)用,而后往復(fù)的是又只有一個(gè)線程能被得到滿足,其他的線程繼續(xù)進(jìn)入阻塞狀態(tài),而這個(gè)時(shí)候可能會(huì)有不斷的增加爭(zhēng)用線程。性能損耗的關(guān)鍵點(diǎn)在于線程的阻塞操作是由操作系統(tǒng)來(lái)完成的,在Linux系統(tǒng)下是由pthread_mutex_lock函數(shù)來(lái)完成。線程被阻塞之后便進(jìn)入了內(nèi)核調(diào)度態(tài),這個(gè)過(guò)程發(fā)生了操作系統(tǒng)將保存用戶態(tài)的上下文進(jìn)入內(nèi)核態(tài),這也就是常說(shuō)的上下文切換,上下文切換代價(jià)大,在于操作系統(tǒng)需要將當(dāng)前線程執(zhí)行上下文內(nèi)容(包括堆棧、寄存器等存儲(chǔ)的內(nèi)容)的保存以便之后線程切換回來(lái)時(shí)候再進(jìn)行現(xiàn)場(chǎng)恢復(fù)。

上面可以看出使用synchronized的代價(jià)是什么了吧,當(dāng)競(jìng)爭(zhēng)激烈的時(shí)候會(huì)引起頻繁的操作系統(tǒng)上下文切換,從而影響系統(tǒng)的性能。下面再來(lái)講講自旋鎖。

自旋鎖的原理

自旋鎖是對(duì)線程阻塞的一種優(yōu)化,他的原理簡(jiǎn)單的說(shuō)就是當(dāng)線程爭(zhēng)用鎖失敗的時(shí)候不立即進(jìn)入阻塞狀態(tài),而是再等一會(huì),因?yàn)閷?duì)于執(zhí)行時(shí)間短的代碼這一會(huì)可能就會(huì)釋放鎖,而線程就不需要進(jìn)行一次阻塞與喚醒。等待操作就是讓線程多執(zhí)行幾個(gè)空指令,至于等待多久這跟具體的處理器實(shí)現(xiàn)有關(guān),也有可能處理器根本不支持自旋鎖,具體實(shí)現(xiàn)的時(shí)候我們可以設(shè)置一個(gè)臨界值,當(dāng)超過(guò)了這個(gè)臨界值之后我們就不自旋了,就乖乖進(jìn)入阻塞狀態(tài)吧。這種優(yōu)化對(duì)于執(zhí)行時(shí)間短的代碼是很有效的。synchronized使用自旋鎖的時(shí)機(jī)是線程進(jìn)入等待隊(duì)列即阻塞的前一步。

關(guān)于偏向鎖

偏向鎖是java6提供的一種功能,主要是對(duì)無(wú)競(jìng)爭(zhēng)條件下的對(duì)加鎖代碼執(zhí)行的優(yōu)化,得到優(yōu)化的地方是省去了對(duì)等待隊(duì)列的更新操作。在競(jìng)爭(zhēng)條件下,獲取鎖失敗的線程會(huì)被放入等待隊(duì)列,這個(gè)隊(duì)列的更新操作是通過(guò)CAS指令來(lái)完成的。對(duì)于那么一段本部應(yīng)該被加鎖的代碼被加了鎖,我們認(rèn)為每次執(zhí)行這段被加了鎖的代碼的時(shí)候更新等待隊(duì)列的操作并不是必要的,而CAS操作會(huì)延遲本地代碼的執(zhí)行,因此偏向鎖是用于優(yōu)化這個(gè)問(wèn)題的。

關(guān)于Lock

Lock是JAVA5增加的內(nèi)容,在JCU(java.util.concurrent.locks)包下面,作者是并發(fā)大師Doug Lea。JCU包提供了很多封裝的鎖,包括常用的ReentrantLock和ReadWriteLock。這些所其實(shí)都是依賴java.util.concurrent.AbstractQueuedSynchronizer這個(gè)類來(lái)實(shí)現(xiàn)的,這個(gè)類有個(gè)簡(jiǎn)寫的名字叫AQS,對(duì)這就是著名的AQS。

關(guān)于Lock,先說(shuō)說(shuō)線程獲取Lock鎖的時(shí)候會(huì)引起哪些事件呢。首先AQS是依賴一個(gè)被volatile修飾的int變量來(lái)標(biāo)識(shí)當(dāng)前鎖的狀態(tài)的,為0的時(shí)候代表當(dāng)前鎖不被任何線程擁有,當(dāng)線程拿到這個(gè)鎖的時(shí)候會(huì)通過(guò)CAS操作修改state的狀態(tài),那么對(duì)于爭(zhēng)用失敗的線程AQS會(huì)怎么辦呢,AQS內(nèi)部維護(hù)了一個(gè)等待隊(duì)列,這個(gè)隊(duì)列是純JAVA實(shí)現(xiàn)的,其實(shí)現(xiàn)也是非常巧妙的,多線程在通過(guò)CAS來(lái)獲取自己在隊(duì)列中的位置,同時(shí)隊(duì)列中的線程狀態(tài)也是阻塞狀態(tài),遇到阻塞就頭疼了,上面已經(jīng)介紹過(guò)阻塞會(huì)帶來(lái)的性能問(wèn)題。在源碼中我們可以看到的是AQS通過(guò)LockSupport(LockSupport底層依賴Unsafe)將線程阻塞,關(guān)于LockSupport我有一篇文章介紹的,其功能是用來(lái)代替wait和notity/notifyall的,更好的地方是LockSupport對(duì)park方法和unpark方法的調(diào)用沒有先后的限制,而notify/notifyall必須在wait調(diào)用之后調(diào)用。盡管如此,這一切并沒有阻止線程進(jìn)入阻塞狀態(tài),我有點(diǎn)失望。

無(wú)鎖時(shí)代

講到無(wú)鎖,必然是Disruptor并發(fā)框架,Disruptor底層依賴一個(gè)RingBuffer來(lái)進(jìn)行線程之間的數(shù)據(jù)交換,無(wú)鎖在于在并發(fā)條件下,多線程對(duì)RingBuffer的讀和寫不會(huì)涉及到鎖,然而因?yàn)镽ingBuffer滿或者RingBuffer中沒有可消費(fèi)內(nèi)容引發(fā)的線程等待,那就要另當(dāng)別論了。簡(jiǎn)單幾句介紹下無(wú)鎖原理,RingBuffer維護(hù)者可讀和可寫的指針,也叫游標(biāo),它指向生產(chǎn)者或消費(fèi)者需要寫或讀的位置,而對(duì)于指針的更新是由CAS來(lái)完成的,這個(gè)過(guò)程中我們不需要加鎖/解鎖的過(guò)程。

后記:

JAVA鎖方面的知識(shí)主要是要搞清楚不同的鎖的優(yōu)點(diǎn)與缺點(diǎn),深入到操作系統(tǒng)層的實(shí)現(xiàn)機(jī)制與不同場(chǎng)景中對(duì)應(yīng)用的性能影響。本文簡(jiǎn)單的擼了一下JAVA鎖從synchronized到無(wú)鎖的發(fā)展以及一些鎖的簡(jiǎn)單原理,主要是拋磚引玉吧,因?yàn)榻榻B的比較簡(jiǎn)單,對(duì)于文中提到的知識(shí)不知道的同學(xué)可以深入了解,我相信你會(huì)很有收獲。有些實(shí)現(xiàn)的原理介紹可能就一句話,但是實(shí)際實(shí)現(xiàn)起來(lái)是蠻復(fù)雜的,需要考慮到的東西是我們沒有寫過(guò)所不能考慮到的。到這里,如果你的項(xiàng)目中用到了多線程并發(fā),你是否會(huì)考慮使用無(wú)鎖模型來(lái)優(yōu)化你項(xiàng)目中多線程之間的通信呢。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5434

    瀏覽量

    124551
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2989

    瀏覽量

    109835
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    EtherCAT運(yùn)動(dòng)控制卡應(yīng)用開發(fā)教程之Java

    運(yùn)動(dòng)控制卡的Java開發(fā)及DLL調(diào)用
    的頭像 發(fā)表于 06-13 14:29 ?228次閱讀
    EtherCAT運(yùn)動(dòng)控制卡應(yīng)用開發(fā)教程之<b class='flag-5'>Java</b>

    Java開發(fā)者必備的效率工具——Perforce JRebel是什么?為什么很多Java開發(fā)者在用?

    Perforce JRebel是一款Java開發(fā)效率工具,旨在幫助java開發(fā)人員更快地編寫更好的應(yīng)用程序。JRebel可即時(shí)重新加載對(duì)代碼的修改,無(wú)需重啟或重新部署應(yīng)用程序,就能讓開發(fā)者即時(shí)看到代碼更改的效果,從而縮短開發(fā)、調(diào)試和測(cè)試周期,大大提升開發(fā)效率。
    的頭像 發(fā)表于 04-27 13:44 ?263次閱讀
    <b class='flag-5'>Java</b>開發(fā)者必備的效率工具——Perforce JRebel是什么?為什么很多<b class='flag-5'>Java</b>開發(fā)者在用?

    Java的SPI機(jī)制詳解

    作者:京東物流 楊葦葦 1.SPI簡(jiǎn)介 SPI(Service Provicer Interface)是Java語(yǔ)言提供的一種接口發(fā)現(xiàn)機(jī)制,用來(lái)實(shí)現(xiàn)接口和接口實(shí)現(xiàn)的解耦。簡(jiǎn)單來(lái)說(shuō),就是系統(tǒng)只需要定義
    的頭像 發(fā)表于 03-05 11:35 ?791次閱讀
    <b class='flag-5'>Java</b>的SPI機(jī)制詳解

    Java應(yīng)用OOM問(wèn)題的排查過(guò)程

    導(dǎo)讀 本文記錄最近一例Java應(yīng)用OOM問(wèn)題的排查過(guò)程,希望可以給遇到類似問(wèn)題的同學(xué)提供參考。 前言:此文記錄最近一例Java應(yīng)用OOM問(wèn)題的排查過(guò)程,希望可以給遇到類似問(wèn)題的同學(xué)提供參考。在本地
    的頭像 發(fā)表于 02-12 11:15 ?663次閱讀
    <b class='flag-5'>Java</b>應(yīng)用OOM問(wèn)題的排查過(guò)程

    SSM框架在Java開發(fā)中的應(yīng)用 如何使用SSM進(jìn)行web開發(fā)

    SSM框架,即Spring、SpringMVC和MyBatis的整合,是Java Web開發(fā)中常用的技術(shù)棧。它通過(guò)分層架構(gòu),實(shí)現(xiàn)了視圖、控制、業(yè)務(wù)邏輯和數(shù)據(jù)訪問(wèn)的分離,提高了代碼的可維護(hù)性和可擴(kuò)展性
    的頭像 發(fā)表于 12-16 17:28 ?1593次閱讀

    Java 23功能介紹

    Java 23 包含全新和更新的 Java 語(yǔ)言功能、核心 API 以及 JVM,同時(shí)適合新的 Java 開發(fā)者和高級(jí)開發(fā)者。從?IntelliJ IDEA 2024.2?開始已支持 Java
    的頭像 發(fā)表于 12-04 10:02 ?1006次閱讀
    <b class='flag-5'>Java</b> 23功能介紹

    Java集合API的改進(jìn)介紹

    解答這些問(wèn)題。 我們將逐步學(xué)習(xí) Java 集合類的優(yōu)化過(guò)程,并按版本逐一對(duì)比分析。主要討論的焦點(diǎn)將包括 JDK 1.0、1.2、1.4、1.5、1.6、1.8、9、10、11 和 21 版本的 Java 集合功能 Java 集合
    的頭像 發(fā)表于 11-22 11:12 ?565次閱讀
    <b class='flag-5'>Java</b>集合API的改進(jìn)介紹

    對(duì)比Python與Java編程語(yǔ)言

    Python與Java都是目前非常流行的編程語(yǔ)言,它們各有其獨(dú)特的優(yōu)勢(shì)和適用場(chǎng)景。以下是對(duì)這兩種編程語(yǔ)言的對(duì)比: 一、語(yǔ)法和易用性 Python 語(yǔ)法簡(jiǎn)潔,代碼更易讀,非常適合初學(xué)者。 動(dòng)態(tài)類型系統(tǒng)
    的頭像 發(fā)表于 11-15 09:31 ?1117次閱讀

    基于Java的工具Power Stage Designer

    電子發(fā)燒友網(wǎng)站提供《基于Java的工具Power Stage Designer.pdf》資料免費(fèi)下載
    發(fā)表于 11-14 16:01 ?11次下載
    基于<b class='flag-5'>Java</b>的工具Power Stage Designer

    Java中時(shí)間戳的使用

    Java中時(shí)間戳的使用
    的頭像 發(fā)表于 11-06 16:04 ?521次閱讀
    <b class='flag-5'>Java</b>中時(shí)間戳的使用

    C語(yǔ)言與Java語(yǔ)言的對(duì)比

    C語(yǔ)言和Java語(yǔ)言都是當(dāng)前編程領(lǐng)域中的重要成員,它們各自具有獨(dú)特的優(yōu)勢(shì)和特點(diǎn),適用于不同的應(yīng)用場(chǎng)景。以下將從語(yǔ)法特性、內(nèi)存管理、跨平臺(tái)性、性能、應(yīng)用領(lǐng)域等多個(gè)方面對(duì)C語(yǔ)言和Java語(yǔ)言進(jìn)行詳細(xì)對(duì)比。
    的頭像 發(fā)表于 10-29 17:31 ?1083次閱讀

    怎么在JAVA中確定線性池大小

    JAVA中確定線性池大小,分別介紹CPU密集型任務(wù)和I/O密集型任務(wù)及其處理方法。
    的頭像 發(fā)表于 10-24 14:02 ?485次閱讀

    ?介紹一款Java開發(fā)的開源MES系統(tǒng)

    ?介紹一款Java開發(fā)的開源MES系統(tǒng),萬(wàn)界星空科技開源的MES系統(tǒng)。該系統(tǒng)基于Java開發(fā),具有廣泛的適用性和高度的可定制性,能夠滿足不同行業(yè)、不同規(guī)模企業(yè)的智能制造需求。
    的頭像 發(fā)表于 09-05 17:39 ?1412次閱讀
    ?介紹一款<b class='flag-5'>Java</b>開發(fā)的開源MES系統(tǒng)

    java反編譯能拿到源碼嗎

    Java反編譯是一種將編譯后的Java字節(jié)碼(.class文件)轉(zhuǎn)換回Java源代碼的過(guò)程。雖然反編譯可以幫助理解代碼的邏輯和結(jié)構(gòu),但它并不總是能完美地還原原始源代碼。反編譯工具通常會(huì)產(chǎn)生與原始代碼
    的頭像 發(fā)表于 09-02 11:03 ?1810次閱讀

    java子類可以繼承父類的什么

    Java是一種面向?qū)ο蟮木幊陶Z(yǔ)言,它支持繼承的概念。繼承是面向?qū)ο缶幊痰娜筇匦灾?,它允許一個(gè)類(稱為子類或派生類)繼承另一個(gè)類(稱為父類或基類)的屬性和方法。在Java中,子類可以繼承父類
    的頭像 發(fā)表于 08-20 11:02 ?2376次閱讀