亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談Java的Synchronized鎖原理和優(yōu)化

 更新時間:2023年05月12日 10:47:39   作者:Java筆記蝦  
這篇文章主要介紹了Java的Synchronized鎖原理和優(yōu)化,synchronized的作用是保證在同一時刻, 被修飾的代碼塊或方法只會有一個線程執(zhí)行,以達到保證并發(fā)安全的效果,需要的朋友可以參考下

一、synchronized介紹

synchronized中文意思是同步,也稱之為”同步鎖“。

synchronized的作用是保證在同一時刻, 被修飾的代碼塊或方法只會有一個線程執(zhí)行,以達到保證并發(fā)安全的效果。

synchronized是Java中解決并發(fā)問題的一種最常用的方法,也是最簡單的一種方法。

在JDK1.5之前synchronized是一個重量級鎖,相對于j.u.c.Lock,它會顯得那么笨重,隨著Javs SE 1.6對synchronized進行的各種優(yōu)化后,synchronized并不會顯得那么重了。

synchronized的作用主要有三個:

  • 原子性: 確保線程互斥地訪問同步代碼;
  • 可見性: 保證共享變量的修改能夠及時可見,其實是通過Java內(nèi)存模型中的 “ 對一個變量unlock操作之前,必須要同步到主內(nèi)存中;如果對一個變量進行l(wèi)ock操作,則將會清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用此變量前,需要重新從主內(nèi)存中l(wèi)oad操作或assign操作初始化變量值 ” 來保證的;
  • 有序性: 有效解決重排序問題,即 “一個unlock操作先行發(fā)生(happen-before)于后面對同一個鎖的lock操作”;

二、synchronized的使用

synchronized的3種使用方式:

  • 修飾實例方法: 作用于當(dāng)前實例加鎖
  • 修飾靜態(tài)方法: 作用于當(dāng)前類對象加鎖
  • 修飾代碼塊: 指定加鎖對象,對給定對象加鎖

1.修飾方法

Synchronized修飾一個方法很簡單,就是在方法的前面加synchronized,synchronized修飾方法和修飾一個代碼塊類似,只是作用范圍不一樣,修飾代碼塊是大括號括起來的范圍,而修飾方法范圍是整個函數(shù)。

  • 方法一:修飾的是一個方法
public synchronized void method()
{
   // todo
}
  • 方法二:修飾的是一個代碼塊
public void method()
{
   synchronized(this) {
      // todo
   }
}

方法一與方法二是等價的,都是鎖定了整個方法時的內(nèi)容。

synchronized關(guān)鍵字不能繼承。雖然可以使用synchronized來定義方法,但synchronized并不屬于方法定義的一部分,因此,synchronized關(guān)鍵字不能被繼承。

  • 在子類方法中加上synchronized關(guān)鍵字
class Parent {
   public synchronized void method() { }
}
class Child extends Parent {
   public synchronized void method() { }
}
  • 在子類方法中調(diào)用父類的同步方法
class Parent {
   public synchronized void method() {   }
}
class Child extends Parent {
   public void method() { super.method();   }
}

注意:

  • 在定義接口方法時不能使用synchronized關(guān)鍵字。
  • 構(gòu)造方法不能使用synchronized關(guān)鍵字,但可以使用synchronized代碼塊來進行同步。

當(dāng)有一個明確的對象作為鎖時,就可以用類似下面這樣的方式寫程序:

public void method3(SomeObject obj)
{
   //obj 鎖定的對象
   synchronized(obj)
   {
      // todo
   }
}

當(dāng)沒有明確的對象作為鎖,只是想讓一段代碼同步時,可以創(chuàng)建一個特殊的對象來充當(dāng)鎖:

class Test implements Runnable
{
   private byte[] lock = new byte[0];  // 特殊的instance變量
   public void method()
   {
      synchronized(lock) {
         // todo 同步代碼塊
      }
   }
   public void run() {
   }
}
  • 2.修飾一個靜態(tài)方法

synchronized也可修飾一個靜態(tài)方法,用法如下:

public synchronized static void method() {
   // todo
}
  • 3.修飾一個類

Synchronized還可作用于一個類,用法如下:

class ClassName {
   public void method() {
      synchronized(ClassName.class) {
         // todo
      }
   }
}

使用總結(jié)

  • 無論synchronized關(guān)鍵字加在方法上還是對象上,如果它作用的對象是非靜態(tài)的,則它取得的鎖是對象;如果synchronized作用的對象是一個靜態(tài)方法或一個類,則它取得的鎖是對類,該類所有的對象同一把鎖。
  • 每個對象只有一個鎖(lock)與之相關(guān)聯(lián),誰拿到這個鎖誰就可以運行它所控制的那段代碼。
  • 實現(xiàn)同步是要很大的系統(tǒng)開銷作為代價的,甚至可能造成死鎖,所以盡量避免無謂的同步控制。

三、synchronized的底層實現(xiàn)

synchronized的底層實現(xiàn),就不得不談數(shù)據(jù)在JVM內(nèi)存的存儲:Java對象頭,以及Monitor對象監(jiān)視器。

對象頭

在JVM中,對象在內(nèi)存中的布局分為三塊區(qū)域:對象頭、實例數(shù)據(jù)和對齊填充。如下圖所示:

ac66e8ed41058ffcb9f66c011e2f2e5c.png

  • 實例數(shù)據(jù): 存放類的屬性數(shù)據(jù)信息,包括父類的屬性信息;
  • 對齊填充: 由于虛擬機要求 對象起始地址必須是8字節(jié)的整數(shù)倍。填充數(shù)據(jù)不是必須存在的,僅僅是為了字節(jié)對齊;
  • 對象頭: Java對象頭一般占有2個機器碼(在32位虛擬機中,1個機器碼等于4字節(jié),也就是32bit,在64位虛擬機中,1個機器碼是8個字節(jié),也就是64bit),但是如果對象是數(shù)組類型,則需要3個機器碼,因為JVM虛擬機可以通過Java對象的元數(shù)據(jù)信息確定Java對象的大小,但是無法從數(shù)組的元數(shù)據(jù)來確認(rèn)數(shù)組的大小,所以用一塊來記錄數(shù)組長度。

synchronized用的鎖就是存在Java對象頭里的,那么什么是Java對象頭呢?Hotspot虛擬機的對象頭主要包括兩部分?jǐn)?shù)據(jù):Mark Word(標(biāo)記字段)、Class Pointer(類型指針)。

其中 Class Pointer是對象指向它的類元數(shù)據(jù)的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例,Mark Word用于存儲對象自身的運行時數(shù)據(jù),它是實現(xiàn)輕量級鎖和偏向鎖的關(guān)鍵。

監(jiān)視器(Monitor)

任何一個對象都有一個Monitor與之關(guān)聯(lián),當(dāng)且一個Monitor被持有后,它將處于鎖定狀態(tài)。

synchronized在JVM里的實現(xiàn)都是 基于進入和退出Monitor對象來實現(xiàn)方法同步和代碼塊同步,雖然具體實現(xiàn)細節(jié)不一樣,但是都可以通過成對的MonitorEnterMonitorExit指令來實現(xiàn)。

  • MonitorEnter指令: 插入在同步代碼塊的開始位置,當(dāng)代碼執(zhí)行到該指令時,將會嘗試獲取該對象Monitor的所有權(quán),即嘗試獲得該對象的鎖;
  • MonitorExit指令: 插入在方法結(jié)束處和異常處,JVM保證每個MonitorEnter必須有對應(yīng)的MonitorExit;

那什么是Monitor?可以把它理解為 一個同步工具,也可以描述為 一種同步機制,它通常被描述為一個對象。

與一切皆對象一樣,所有的Java對象是天生的Monitor,每一個Java對象都有成為Monitor的潛質(zhì),因為在Java的設(shè)計中 ,每一個Java對象自打娘胎里出來就帶了一把看不見的鎖,它叫做內(nèi)部鎖或者Monitor鎖。

也就是通常說Synchronized的對象鎖,MarkWord鎖標(biāo)識位為10,其中指針指向的是Monitor對象的起始地址。在Java虛擬機(HotSpot)中,Monitor是由ObjectMonitor實現(xiàn)的。

四、synchronized 鎖的升級順序

鎖解決了數(shù)據(jù)的安全性,但是同樣帶來了性能的下降。hotspot 虛擬機的作者經(jīng)過調(diào)查發(fā)現(xiàn),大部分情況下,加鎖的代碼不僅僅不存在多線程競爭,而且總是由同一個線程多次獲得。所以基于這樣一個概率。

synchronized 在JDK1.6 之后做了一些優(yōu)化,為了減少獲得鎖和釋放鎖來的性能開銷,引入了偏向鎖、輕量級鎖、自旋鎖、重量級鎖,鎖的狀態(tài)根據(jù)競爭激烈的程度從低到高不斷升級。

鎖主要存在四種狀態(tài),依次是:無鎖狀態(tài)、偏向鎖狀態(tài)、輕量級鎖狀態(tài)、重量級鎖狀態(tài),鎖可以從偏向鎖升級到輕量級鎖,再升級的重量級鎖。但是鎖的升級是單向的,也就是說只能從低到高升級,不會出現(xiàn)鎖的降級。而且這個過程就是開銷逐漸加大的過程。

bd330342c2dac1f0674970e62bda2c82.png

到此這篇關(guān)于淺談Java的Synchronized鎖原理和優(yōu)化 的文章就介紹到這了,更多相關(guān)Synchronized鎖原理和優(yōu)化 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot項目使用html5的video標(biāo)簽完成視頻播放功能

    Springboot項目使用html5的video標(biāo)簽完成視頻播放功能

    這篇文章主要介紹了Springboot項目使用html5的video標(biāo)簽完成視頻播放功能,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • 在Mac OS上安裝Java以及配置環(huán)境變量的基本方法

    在Mac OS上安裝Java以及配置環(huán)境變量的基本方法

    這篇文章主要介紹了在Mac OS上安裝Java以及配置環(huán)境變量的基本方法,包括查看所安裝Java版本的方法,需要的朋友可以參考下
    2015-10-10
  • Java并發(fā)之搞懂讀寫鎖

    Java并發(fā)之搞懂讀寫鎖

    這篇文章主要介紹了Java并發(fā)之讀寫鎖,文中相關(guān)實例代碼詳細,測試可用,具有一定參考價值,需要的朋友可以了解下,希望能夠給你帶來幫助
    2021-11-11
  • 詳解Java代碼常見優(yōu)化方案

    詳解Java代碼常見優(yōu)化方案

    這篇文章主要介紹了Java代碼常見優(yōu)化方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java中使用Preconditions來檢查傳入?yún)?shù)介紹

    Java中使用Preconditions來檢查傳入?yún)?shù)介紹

    這篇文章主要介紹了Java中使用Preconditions來檢查傳入?yún)?shù)介紹,本文只是作為一個簡單的用法介紹,需要的朋友可以參考下
    2015-06-06
  • Java getRealPath(

    Java getRealPath("/")與getContextPath()區(qū)別詳細分析

    這篇文章主要介紹了Java getRealPath("/")與getContextPath()區(qū)別詳細分析,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • maven如何動態(tài)統(tǒng)一修改版本號的方法步驟

    maven如何動態(tài)統(tǒng)一修改版本號的方法步驟

    這篇文章主要介紹了maven如何動態(tài)統(tǒng)一修改版本號的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java使用NIO包實現(xiàn)Socket通信的實例代碼

    Java使用NIO包實現(xiàn)Socket通信的實例代碼

    本篇文章主要介紹了Java使用NIO包實現(xiàn)Socket通信的實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Java語言實現(xiàn)簡單FTP軟件 FTP軟件遠程窗口實現(xiàn)(6)

    Java語言實現(xiàn)簡單FTP軟件 FTP軟件遠程窗口實現(xiàn)(6)

    這篇文章主要為大家詳細介紹了Java語言實現(xiàn)簡單FTP軟件,F(xiàn)TP軟件遠程窗口的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Java常用對象操作工具代碼實例

    Java常用對象操作工具代碼實例

    這篇文章主要介紹了Java常用對象操作工具代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-12-12

最新評論