国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

淺談Java中鎖的實現和優化

DevWiki / 1413人閱讀

摘要:這兩種策略的區別就在于,公平策略會讓等待時間長的線程優先執行,非公平策略則是等待時間長的線程不一定會執行,存在一個搶占資源的問題。

之前有一篇文章我們簡單的談到了Java中同步的問題,但是可能在平常的開發中,有些理論甚至是某些方式是用不到的,但是從程序的角度看,這些理論思想我們可以運用到我們的開發中,比如是不是應該一談到同步問題,就應該想到用synchronized?,什么時候應該用ReentrantLock?,是不是應該考慮用原子類解決某些問題?那我們就來聊一聊我們如何用這個鎖。

上一篇文章中第一個例子,我們后來通過對方法加synchronized修改了代碼,在這里還有一種修改方式,我們可以考慮使用原子類,這樣也可以解決這個問題,我們來看看偽代碼:

private static AtomicInteger i = new AtomicInteger(0);

private static void increse(){
        i.incrementAndGet();
    }

因為在這個問題上,不只是有線程的可見性問題,還有一個就是操作的原子性問題,說到這里,我們應該明白,在我們平常的開發中,有時候應該區分什么時候是需要原子操作,什么時候只需要可見性,那么這樣我們才能夠正確的判斷用某種合理的方式寫出合理的代碼。

好,這是上次的一點小問題我們再這里重復一下,接下來我們聊一聊具體的鎖。

互斥同步

synchronized就是一個很典型的例子,這種鎖也叫做可重入鎖,就是一個線程持有一個相同的鎖對象,可以進行重復加解鎖,換句話說,持有相同鎖對象的線程不會自己把自己鎖住。

還有另外一個和synchronized很相近的鎖,就是我們上面提到的ReentrantLock,這個和synchronized一樣,都提供了可重入性,這兩個鎖的效果是差不多的(在以前的一些比較舊的JDK版本中,并發數比較大的情況下,ReentrantLock的性能是要優于synchronized的),可能有些小伙伴還沒有用過這種鎖,那這里我們就簡單說一下具體用法:

ReentrantLock lock = new ReentrantLock();

lock.lock();
// code
lock.unlock();

這里從API的層面提供了一個比較簡單的寫法,同時也提供了一些比較高級的特性,像信號量,線程終止等等,有興趣的小伙伴可以去查閱相關資料去了解一下,在這里我們不深入探討,但是有一個地方需要注意一下,就是ReentrantLock提供了兩種競爭策略,一種是公平策略,另一種是非公平策略。

ReentrantLock lock = new ReentrantLock();// 非公平策略

ReentrantLock lock = new ReentrantLock(true);// 公平策略

公平策略與非公平策略

這里我就先舉一個比較簡單的例子,如果我們在公司上班,有時候我們中午會帶午飯,然后需要用微波爐來加熱一下,那這里就有個問題了,在我們去加熱午飯的時候,如果前面有同事在排隊,當然了,我們都是有素質的人,出于禮貌,我們也需要排隊,等待前面的同事操作完,后面來的同事當然也需要排在我們后面,那這種情況下,我們可以稱之為公平策略。
如果在前面正在熱午飯的同事,他有關系比較好的同事也來熱午飯,這個時候是否可以插隊,如果這位同事插隊成功了,那么他就可以繼續熱午飯了,那么我們又得在后面等了,這種情況我們可以稱之為非公平策略。這兩種策略的區別就在于,公平策略會讓等待時間長的線程優先執行,非公平策略則是等待時間長的線程不一定會執行,存在一個搶占資源的問題。如果從源碼的角度來看,那么我們就來簡單的說一下非公平策略的執行方式。

非公平策略執行方式

一個線程首先會試探性的獲取一次鎖,如果獲取到,則將當前鎖設置為該線程獨占,如果沒有設置成功,則再次試探性的獲取一次,如果還是沒有成功,則將該線程加入到等待隊列,后面再次等待獲取,看到這里,可能有一些小伙伴不太明白了,那么非公平是體現在哪里,如果排在你前面的以為同事剛好熱好午飯,然后你在后面玩手機,前面的同事還沒有跟你說,“喂,該你去熱午飯了。”,然后這會兒又來了一個其他人插隊,那么作為高素質的你,肯定不能和別人計較了,好了,那就等著吧,非公平策略就體現在這里了。這里實現的方式很復雜,可以一點一點去看,其中有用到AQS,CAS等這些比較底層的原理,值得一提的是,現在JVMsynchronized的優化已經相當不錯,其性能表型已經和ReentrantLock不相上下,如果從推薦的角度來說,還是推薦使用synchronized,除非需要使用一些比較高級的特性。

非互斥同步

接下來我們再來聊一聊什么是非互斥同步,互斥同步就是指阻塞同步,就是阻塞線程讓其一直等待某個鎖可用的過程,那么非互斥同步剛和和這個是對立的,這里用到了一個CAS的原理,這個是操作系統的指令,即compare and swap,比較并交換,說的簡單一點,就是如果在內存中一個值為V,然后我們又一個預估值A,然后還有一個新值B,如果V和A相同,那么就把V的值替換為B,然后返回V,這里要說一下,無論是否能替換成功,都會返回V的值,這個過程稱作CAS。這種就涉及到操作系統級別了,因為在之前的阻塞同步中,阻塞線程然后再將其恢復獲得鎖的過程,是比較耗費性能的,我們知道,Java中的線程是對操作系統線程的一個映射,如果我們在阻塞同步的時候,將一個線程掛起,然后再恢復,那么這里要經歷一個向核心態的轉換過程,消耗是比較巨大的。因此,在非互斥同步中,通過CAS這種方式,能夠相對比較好的處理這個問題,但是有個問題需要明確一下,就是在Java中,這種處理方式,是通過這個類來完成的,sun.misc.Unsafe,這個類只能通過boot class loader來調用,要么就是通過反射,或者通過某些方法來調用,比如AtomicInteger類中的incrementAndGet()方法,當然,還有很多這種方法,個人也是對CAS這種機制理解的比較片面,還需要更加深層次的研究。到這里,我們不得不說,Doug Lea的編碼能力實屬上乘,確實佩服!

鎖優化

我們再來談一談鎖優化,JVM為我們的代碼或者說其內部就做了一些優化方式,我們就來簡單的說幾個。

自旋

什么是自旋,是的,有些小伙伴也可以這么理解,就是自己旋轉,當然這是開個玩笑,不過這種方式對于阻塞線程來說,是有一定的效果,簡單來說,就是如果一個線程獲得了鎖,然后另一個線程按照以前的方式只能阻塞等待,那么JVM對這里做了一個優化,就是讓這種等待的線程去執行一個循環,但是此時CPU的時間片是不會讓出去的,也就是說這里的這個線程還是占有著一個處理時間,如果循環結束之后,這個鎖就能獲取了,那這個線程就拿到這個鎖繼續執行,這樣做的一個目的就在于我們上面說的,線程從掛起到恢復需要像核心態的一個轉換,這個性能的消耗和占用時間片的消耗比是很大的,但是同時也有一個問題就是如果自旋結束后,還是沒有獲得鎖,那么這段時間性能的消耗就是浪費了,所以也很難權衡,因此在一些比較舊的JDK版本中,JVM是禁止使用自旋的。

自適應自旋

這里就是說如果一個線程在一次成功的自旋結束后,并且成功的獲得了鎖然后成功運行,那么JVM會“認為”這次自旋是成功的,那么下次如果繼續有線程發生自旋,那么JVM能夠判斷出來是否需要讓這個線程自旋來減少性能的消耗,從這里來看,JVM還是相對比較“機智”的。

鎖消除

這個例子在上一篇文章中曾經提到過,對于字符串的拼接,我們反編譯就能看出來,如果能夠判斷不存在方法逃逸的情況下,那么JVM會對這種操作轉換為StringBuilderappend操作,可能有的小伙伴會有疑問,為什么不轉換為StringBuffer呢?因為JVM已經能夠正確判斷出沒有方法逃逸,那么如果再用線程安全類來處理也意義不大。

好了,這篇文章就先到這里了,這里只是很簡略的聊了一下在Java中的鎖的相關知識,更深入的還有待后面繼續研究。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76670.html

相關文章

  • 淺談Java鎖的問題

    摘要:之前我們簡單的討論了一下關于中的同步還有一些鎖優化的問題,今天我們就來簡單的聊一聊關于中的死鎖問題。這里顯示兩個線程的狀態現在是處于阻塞狀態,然后都在等待鎖的獲取,我們再繼續往下看。 之前我們簡單的討論了一下關于Java中的同步還有一些鎖優化的問題,今天我們就來簡單的聊一聊關于Java中的死鎖問題。 這個問題我們在開發的時候,或多或少都能遇到,對業務邏輯沒有正確的梳理,又或者是在多線程...

    fox_soyoung 評論0 收藏0
  • 【推薦】最新200篇:技術文章整理

    摘要:作為面試官,我是如何甄別應聘者的包裝程度語言和等其他語言的對比分析和主從復制的原理詳解和持久化的原理是什么面試中經常被問到的持久化與恢復實現故障恢復自動化詳解哨兵技術查漏補缺最易錯過的技術要點大掃盲意外宕機不難解決,但你真的懂數據恢復嗎每秒 作為面試官,我是如何甄別應聘者的包裝程度Go語言和Java、python等其他語言的對比分析 Redis和MySQL Redis:主從復制的原理詳...

    BicycleWarrior 評論0 收藏0
  • 【推薦】最新200篇:技術文章整理

    摘要:作為面試官,我是如何甄別應聘者的包裝程度語言和等其他語言的對比分析和主從復制的原理詳解和持久化的原理是什么面試中經常被問到的持久化與恢復實現故障恢復自動化詳解哨兵技術查漏補缺最易錯過的技術要點大掃盲意外宕機不難解決,但你真的懂數據恢復嗎每秒 作為面試官,我是如何甄別應聘者的包裝程度Go語言和Java、python等其他語言的對比分析 Redis和MySQL Redis:主從復制的原理詳...

    tommego 評論0 收藏0
  • 淺談java中的并發控制

    摘要:并發需要解決的問題功能性問題線程同步面臨兩個問題,想象下有兩個線程在協作工作完成某項任務。鎖可用于規定一個臨界區,同一時間臨界區內僅能由一個線程訪問。并發的數據結構線程安全的容器,如等。 并發指在宏觀上的同一時間內同時執行多個任務。為了滿足這一需求,現代的操作系統都抽象出 線程 的概念,供上層應用使用。 這篇博文不打算詳細展開分析,而是對java并發中的概念和工具做一個梳理。沿著并發模...

    Gilbertat 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<