最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一篇文章輕松搞懂Java中的自旋鎖

 更新時(shí)間:2019年05月07日 09:47:51   作者:深夜里的程序猿  
隨著互聯(lián)網(wǎng)的蓬勃發(fā)展,越來越多的互聯(lián)網(wǎng)企業(yè)面臨著用戶量膨脹而帶來的并發(fā)安全問題。這篇文章主要給大家介紹了關(guān)于Java中自旋鎖的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

鎖作為并發(fā)共享數(shù)據(jù),保證一致性的工具,在JAVA平臺(tái)有多種實(shí)現(xiàn)(如 synchronized 和 ReentrantLock等等 ) 。這些已經(jīng)寫好提供的鎖為我們開發(fā)提供了便利。

在之前的文章《一文徹底搞懂面試中常問的各種“鎖” 》中介紹了Java中的各種“鎖”,可能對(duì)于不是很了解這些概念的同學(xué)來說會(huì)覺得有點(diǎn)繞,所以我決定拆分出來,逐步詳細(xì)的介紹一下這些鎖的來龍去脈,那么這篇文章就先來會(huì)一會(huì)“自旋鎖”。

正文

出現(xiàn)原因

在我們的程序中,如果存在著大量的互斥同步代碼,當(dāng)出現(xiàn)高并發(fā)的時(shí)候,系統(tǒng)內(nèi)核態(tài)就需要不斷的去掛起線程和恢復(fù)線程,頻繁的此類操作會(huì)對(duì)我們系統(tǒng)的并發(fā)性能有一定影響。同時(shí)聰明的JVM開發(fā)團(tuán)隊(duì)也發(fā)現(xiàn),在程序的執(zhí)行過程中鎖定“共享資源“的時(shí)間片是極短的,如果僅僅是為了這點(diǎn)時(shí)間而去不斷掛起、恢復(fù)線程的話,消耗的時(shí)間可能會(huì)更長,那就“撿了芝麻丟了西瓜”了。

而在一個(gè)多核的機(jī)器中,多個(gè)線程是可以并行執(zhí)行的。如果當(dāng)后面請求鎖的線程沒拿到鎖的時(shí)候,不掛起線程,而是繼續(xù)占用處理器的執(zhí)行時(shí)間,讓當(dāng)前線程執(zhí)行一個(gè)忙循環(huán)(自旋操作),也就是不斷在盯著持有鎖的線程是否已經(jīng)釋放鎖,那么這就是傳說中的自旋鎖了。

自旋鎖開啟

雖然在JDK1.4.2的時(shí)候就引入了自旋鎖,但是需要使用“-XX:+UseSpinning”參數(shù)來開啟。在到了JDK1.6以后,就已經(jīng)是默認(rèn)開啟了。下面我們自己來實(shí)現(xiàn)一個(gè)基于CAS的簡易版自旋鎖。

public class SimpleSpinningLock {

 /**
 * 持有鎖的線程,null表示鎖未被線程持有
 */
 private AtomicReference<Thread> ref = new AtomicReference<>();

 public void lock(){
 Thread currentThread = Thread.currentThread();
 while(!ref.compareAndSet(null, currentThread)){
  //當(dāng)ref為null的時(shí)候compareAndSet返回true,反之為false
  //通過循環(huán)不斷的自旋判斷鎖是否被其他線程持有
 }
 }

 public void unLock() {
 Thread cur = Thread.currentThread();
 if(ref.get() != cur){
  //exception ...
 }
 ref.set(null);
 }
}

簡簡單單幾行代碼就實(shí)現(xiàn)了一個(gè)簡陋的自旋鎖,下面我們來測試一下

public class TestLock {

 static int count = 0;

 public static void main(String[] args) throws InterruptedException {
 ExecutorService executorService = Executors.newFixedThreadPool(100);
 CountDownLatch countDownLatch = new CountDownLatch(100);
 SimpleSpinningLock simpleSpinningLock = new SimpleSpinningLock();
 for (int i = 0 ; i < 100 ; i++){
  executorService.execute(new Runnable() {
  @Override
  public void run() {
   simpleSpinningLock.lock();
   ++count;
   simpleSpinningLock.unLock();
   countDownLatch.countDown();
  }
  });

 }
 countDownLatch.await();
 System.out.println(count);
 }
}

// 多次執(zhí)行輸出均為:100 ,實(shí)現(xiàn)了鎖的基本功能

通過上面的代碼可以看出,自旋就是在循環(huán)判斷條件是否滿足,那么會(huì)有什么問題嗎?如果鎖被占用很長時(shí)間的話,自旋的線程等待的時(shí)間也會(huì)變長,白白浪費(fèi)掉處理器資源。因此在JDK中,自旋操作默認(rèn)10次,我們可以通過參數(shù)“-XX:PreBlockSpin”來設(shè)置,當(dāng)超過來此參數(shù)的值,則會(huì)使用傳統(tǒng)的線程掛起方式來等待鎖釋放。

自適應(yīng)自旋鎖

隨著JDK的更新,在1.6的時(shí)候,又出現(xiàn)了一個(gè)叫做“自適應(yīng)自旋鎖”的玩意。它的出現(xiàn)使得自旋操作變得聰明起來,不再跟之前一樣死板。所謂的“自適應(yīng)”意味著對(duì)于同一個(gè)鎖對(duì)象,線程的自旋時(shí)間是根據(jù)上一個(gè)持有該鎖的線程的自旋時(shí)間以及狀態(tài)來確定的。例如對(duì)于A鎖對(duì)象來說,如果一個(gè)線程剛剛通過自旋獲得到了鎖,并且該線程也在運(yùn)行中,那么JVM會(huì)認(rèn)為此次自旋操作也是有很大的機(jī)會(huì)可以拿到鎖,因此它會(huì)讓自旋的時(shí)間相對(duì)延長。但是如果對(duì)于B鎖對(duì)象自旋操作很少成功的話,JVM甚至可能直接忽略自旋操作。因此,自適應(yīng)自旋鎖是一個(gè)更加智能,對(duì)我們的業(yè)務(wù)性能更加友好的一個(gè)鎖。

結(jié)語

本來想著在一篇文章里面把“自旋鎖”,“鎖消除”,“鎖粗化”等一些鎖優(yōu)化的概念都介紹完成的,但是發(fā)現(xiàn)可能篇幅會(huì)比較大,對(duì)于沒怎么接觸過這一塊的同學(xué)來說理解起來會(huì)比較吃力,所以決定分開多個(gè)章節(jié)介紹,希望大家都不懂的地方可以多看幾遍,慢慢體會(huì),相信你會(huì)有所收獲的。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Java 設(shè)置Excel條件格式示例代碼(高亮條件值、應(yīng)用單元格值/公式/數(shù)據(jù)條等類型)

    Java 設(shè)置Excel條件格式示例代碼(高亮條件值、應(yīng)用單元格值/公式/數(shù)據(jù)條等類型)

    這篇文章主要介紹了Java 設(shè)置Excel條件格式示例代碼(高亮條件值、應(yīng)用單元格值/公式/數(shù)據(jù)條等類型),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • MyBatis的配置對(duì)象Configuration作用及說明

    MyBatis的配置對(duì)象Configuration作用及說明

    MyBatis的Configuration對(duì)象是MyBatis的核心配置對(duì)象,它包含了MyBatis運(yùn)行時(shí)所需的幾乎所有配置信息,這個(gè)對(duì)象負(fù)責(zé)管理MappedStatement、創(chuàng)建核心組件、提供配置信息的訪問接口以及作為插件機(jī)制的入口
    2025-03-03
  • SpringBoot+Mybatis分頁插件PageHelper實(shí)現(xiàn)分頁效果

    SpringBoot+Mybatis分頁插件PageHelper實(shí)現(xiàn)分頁效果

    這篇文章主要介紹了SpringBoot+Mybatis實(shí)現(xiàn)分頁效果,本案例是采用Mybatis分頁插件PageHelper實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-11-11
  • 關(guān)于junit測試需要的依賴

    關(guān)于junit測試需要的依賴

    這篇文章主要介紹了關(guān)于junit測試需要的依賴,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 淺談導(dǎo)入JavaWeb 項(xiàng)目出現(xiàn)的問題

    淺談導(dǎo)入JavaWeb 項(xiàng)目出現(xiàn)的問題

    這篇文章主要介紹了導(dǎo)入JavaWeb 項(xiàng)目出現(xiàn)的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 解決java.util.HashMap$Values?cannot?be?cast?to?java.ut的問題

    解決java.util.HashMap$Values?cannot?be?cast?to?java.ut的問題

    這篇文章主要介紹了解決java.util.HashMap$Values?cannot?be?cast?to?java.ut的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java設(shè)置String字符串編碼方法詳解

    Java設(shè)置String字符串編碼方法詳解

    因?yàn)镾tring字符串很常用,所以我們在使用它的過程中,可能會(huì)面臨各種問題,比如”中文亂碼“問題等,那么為什么中文會(huì)亂碼?本文將給大家介紹一下Java如何設(shè)置String字符串編碼,來避免和解決這一常見問題,需要的朋友可以參考下
    2023-05-05
  • idea中定時(shí)及多數(shù)據(jù)源配置方法

    idea中定時(shí)及多數(shù)據(jù)源配置方法

    因項(xiàng)目要求,需要定時(shí)從達(dá)夢數(shù)據(jù)庫中取數(shù)據(jù),并插入或更新到ORACLE數(shù)據(jù)庫中,這篇文章主要介紹了idea中定時(shí)及多數(shù)據(jù)源配置方法,需要的朋友可以參考下
    2023-12-12
  • java中String與StringBuilder的區(qū)別

    java中String與StringBuilder的區(qū)別

    本篇文章介紹了,java中String與StringBuilder的區(qū)別。需要的朋友參考下
    2013-04-04
  • Java實(shí)現(xiàn)基于UDP協(xié)議的網(wǎng)絡(luò)通信UDP編程

    Java實(shí)現(xiàn)基于UDP協(xié)議的網(wǎng)絡(luò)通信UDP編程

    在Java中使用UDP編程,仍然需要使用Socket,因?yàn)閼?yīng)用程序在使用UDP時(shí)必須指定網(wǎng)絡(luò)接口(IP地址)和端口號(hào)。注意:UDP端口和TCP端口雖然都使用0~65535,但他們是兩套獨(dú)立的端口,即一個(gè)應(yīng)用程序用TCP占用了端口1234,不影響另一個(gè)應(yīng)用程序用UDP占用端口1234
    2023-04-04

最新評(píng)論

长泰县| 肥城市| 会东县| 临城县| 栾城县| 嘉善县| 明星| 涡阳县| 宁河县| 清新县| 开封市| 巴彦县| 邯郸市| 怀集县| 萍乡市| 左云县| 永德县| 大渡口区| 中卫市| 富蕴县| 淮滨县| 灵台县| 嫩江县| 马尔康县| 尚义县| 曲周县| 图片| 乐东| 宜良县| 卢龙县| 托里县| 墨脱县| 棋牌| 改则县| 太白县| 海原县| 益阳市| 珠海市| 辉县市| 屏东市| 庄浪县|