日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 同步锁_Java多线程:synchronized同步锁的使用和实现原理

發(fā)布時間:2025/3/15 java 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 同步锁_Java多线程:synchronized同步锁的使用和实现原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作用和用法

  • 在多線程對共享資源進行并發(fā)訪問方面,JDK提供了synchronized關(guān)鍵字來進行線程同步,實現(xiàn)多線程并發(fā)訪問的線程安全。synchronized的作用主要體現(xiàn)在三個方面:(1)確保線程互斥地訪問同步代碼;(2)保證共享變量的線程可見性;(3)禁止指令重排。其中(2)和(3)相當于volatile關(guān)鍵字的作用。
  • synchronized可以用在代碼的以下地方:

(1)靜態(tài)方法:將類對象自身作為monitor對象,對該類所有使用了sychronized修飾的靜態(tài)方法進行同步,即任何時候只能存在一個線程在調(diào)用該類的使用了synchronized修飾的靜態(tài)方法,其他調(diào)用了該類的使用了synchronized修飾的靜態(tài)方法的線程需要阻塞;

(2)普通成員方法:使用類的對象實例作為monitor對象,該類所有使用了synchronized修飾的成員方法,在任何時刻只能被一個線程訪問,其他線程需要阻塞;

(3)代碼塊:使用某個對象作為monitor對象,通常為一個普通的private成員變量,如private Object object = new Object();,這樣所有使用了該object對象的同步塊,在任何時候只能存在一個線程訪問。

  • synchronized可以與monitor對象的wait,notify,notifyAll方法一起來使用,實現(xiàn)線程之間的通信,如實現(xiàn)生產(chǎn)者和消費者模型。其中多個線程共享一個monitor對象,在線程持有synchronized鎖時,才能調(diào)用monitor的wait,notify或者notifyAll,分別用于釋放monitor鎖,阻塞休眠,等待其他線程;通知和喚醒其中一個阻塞休眠的線程,讓該線程去獲取monitor鎖;通知所有阻塞休眠的線程去競爭monitor鎖。
  • synchronized使用方便,無需顯示地在應(yīng)用代碼中加鎖和解鎖,只需在對應(yīng)的方法或者代碼塊中使用synchronized關(guān)鍵字修飾即可,由JVM自身實現(xiàn)自動地加鎖和釋放鎖。
  • synchronized修飾的范圍越小,線程并發(fā)度越高,性能越好,所以通常使用同步代碼塊,而不是同步方法來縮小同步范圍,優(yōu)化性能。

實現(xiàn)原理

JVM層面

  • synchronized關(guān)鍵字是基于JVM提供的monitorenter和monitorexit字節(jié)碼指令,以及結(jié)合監(jiān)視器monitor來實現(xiàn)的。
  • 由上面的分析可知,synchronized關(guān)鍵字用在靜態(tài)方法,普通成員方法,代碼塊中,分別需要以類對象自身,類的對象實例,某個普通對象作為對應(yīng)的monitor對象。
  • 由JVM的相關(guān)知識可知,任何java類都需要編譯成class字節(jié)碼,然后加載到JVM當中去執(zhí)行。而在編譯一個java類生成對應(yīng)class字節(jié)碼時,當遇到sychronized關(guān)鍵字時,會在sychronized關(guān)鍵字所修飾的方法或者代碼塊的開始處:增加一個monitorenter字節(jié)碼指令,在方法或者代碼塊的結(jié)束處:增加monitorexit字節(jié)碼指令,即使用monitorenter和monitorexit字節(jié)碼指令包圍該方法或者代碼塊對應(yīng)的字節(jié)碼。如下:
  • 在類的成員方法中使用synchronized關(guān)鍵字:
  • 反編譯該類對應(yīng)的class字節(jié)碼文件:在成員方法method對應(yīng)的字節(jié)碼周圍使用了monitorenter和monitorexit字節(jié)碼指令。

monitorenter和monitorexit指令的作用為:

  • monitorenter的作用:所有線程共享該同步代碼和該對象關(guān)聯(lián)的監(jiān)視器monitor,每個線程執(zhí)行到monitorenter指令的時候,會檢查對應(yīng)的monitor對象的計數(shù)是否為0,是則當前線程成為該monitor對象的owner,即鎖住該monitor對象了,并遞增該計數(shù)為1,之后該線程每調(diào)用一次使用了該monitor對象進行同步的方法,計數(shù)加一(所以synchronized也是可重入的);其他線程檢查到monitor對象的計數(shù)不為0,則知道該monitor對象已經(jīng)被其他線程持有鎖住了,故當前線程會阻塞直到該monitor的計數(shù)重新變?yōu)?,則阻塞的線程們會繼續(xù)競爭成為該monitor的owner,從而可以訪問同步代碼。
  • monitorexit的作用:當持有該monitor對象的線程每執(zhí)行完一個同步代碼時(如對于成員方法,如果該線程調(diào)用了多個使用sychronized修飾的成員方法,則每個方法執(zhí)行完執(zhí)行一次monitor減一),將monitor的計數(shù)減一,當monitor對象的計數(shù)遞減到0時,則當前線程不再持有該monitor對象,其他阻塞的線程此時可以競爭成為該monitor的owner,成功的線程可以訪問同步代碼。
  • 為什么monitor對象的wait,notify,notifyAll需要在synchronized同步代碼里面使用呢?首先需要理解以下概念:
  • 每個對象關(guān)聯(lián)一個監(jiān)視器monitor;
  • 每個監(jiān)視器monitor都有一個該對象的鎖(即計數(shù)是否為0,為0則說明沒有其他線程加鎖),一個等待隊列和一個同步隊列;
    • wait方法:釋放對象鎖,然后進入等待隊列;
    • notify和notifyAll方法:從等待隊列被喚醒,放到同步隊列去競爭該對象鎖;
    • 所以線程在執(zhí)行wait,notify,notifyAll時需要依賴該監(jiān)視器monitor,即該線程成為該監(jiān)視器的owner,從而可以訪問synchronized包圍的同步代碼,這樣才能有權(quán)訪問該監(jiān)視器對應(yīng)的對象鎖,等待隊列和同步隊列。

    操作系統(tǒng)層面

    • 在操作系統(tǒng)層面,synchronized是基于操作系統(tǒng)的Metux Lock來實現(xiàn)的,而操作系統(tǒng)實現(xiàn)線程之間的切換是需要進行上下文切換的,即從用戶態(tài)切換到內(nèi)核態(tài),所以這也是synchronized相對來說成本較高,性能相對較低的原因。
    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

    總結(jié)

    以上是生活随笔為你收集整理的java 同步锁_Java多线程:synchronized同步锁的使用和实现原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。