java中synchronized關鍵字基礎-1

来源:https://www.cnblogs.com/yangblogFamily/archive/2022/06/07/16351916.html
-Advertisement-
Play Games

1、synchronized關鍵字簡介 synchronized是java中的一個關鍵字,在中文中為同步,也被稱之為'同步鎖',以此來達到多線程併發訪問時候的併發安全問題,可以用來修飾代碼塊、非靜態方法。靜態方法等; 修飾代碼塊時:給當前指定的對象加鎖 修飾非靜態方法時:作用於當前實例加鎖 修飾靜態 ...


1、synchronized關鍵字簡介

synchronized是java中的一個關鍵字,在中文中為同步,也被稱之為'同步鎖',以此來達到多線程併發訪問時候的併發安全問題,可以用來修飾代碼塊、非靜態方法。靜態方法等;
修飾代碼塊時:給當前指定的對象加鎖
修飾非靜態方法時:作用於當前實例加鎖
修飾靜態方法時:作用於當前類對象加鎖
synchronized在java記憶體模型中的主要作用
原子性:通過monitorenter和monitorexit指令,保證被synchronized修飾的代碼在同一時間只能被一個線程訪問,在鎖未釋放之前,無法被其他線程訪問到
可見性:保證共用變數的修改能夠及時可見,對一個變數的unlock操作之前,必須把此變數同步回主記憶體中(store和write操作)
有序性:一個變數在同一時刻只允許一條線程對其執行lock操作,這條規則決定了持有同一個鎖的兩個同步塊只能串列執行

2、synchronized修飾代碼塊

當synchronized修飾代碼塊時,有以下幾種情況

1、this關鍵字
點擊查看代碼
synchronized(this){   
//互斥代碼
 }

這裡的this就是等價於調用這個方法的對象,synchronized鎖的就是this這個對象的鎖,若有多個對象調用方法,各個對象鎖之間相互獨立,互不影響

2、Class.class
點擊查看代碼
synchronized(Test.class){     
//互斥代碼
}

這裡synchronized鎖的對象為類鎖,在需要類鎖的代碼不能同時執行,但是與非需要類鎖的對象鎖或者與沒有加鎖的代碼可以同時執行
用synchronized進行加鎖時看獲得鎖是對象還是類的鎖,還有的是synchronized鎖住的是一個對象或者類(其實也是對象),而不是方法或者代碼段。

3、synchronized修飾實例方法

點擊查看代碼
public  synchronized void method(){     //代碼
 }

當synchronized修飾實例方法時,鎖的是該類的實例對象

4、synchronized修飾靜態方法

點擊查看代碼
public synchronized static void method() {     // todo
 }

由於static靜態方法是屬於類的而不屬於對象的,所以synchronized修飾的靜態方法鎖定的是這個類的所有對象

5、synchronized的底層實現原理

在java記憶體模型中,synchronized可以保證原子性、有序性、可見性,在這之前,先談談對象在HotSpot虛擬機中的分佈,主要有三部:對象頭(Header)、實例數據(Instance Data)和對象填充(Padding)

對象頭

對象頭主要包括兩部分信息,第一部分用於存儲對象自身的運行時數據、如哈希碼(HashCode)、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等,官方稱之為'Mark Word',還有一部分稱之為類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例
存儲內容標誌位狀態對象哈希碼、對象分代年齡01未鎖定指向鎖記錄的指針00輕量級鎖定指向重量級鎖的指針10膨脹(重量級鎖定)空,不需要記錄信息11GC標識偏向線程ID、偏向時間戳、對象分代年齡01可偏向

實例數據

實例數據部分是對象真正存儲的有效信息,即我們在程式代碼裡面所定義的各種類型的欄位內容,無論是從父類繼承下來的,還是在子類中定義的欄位都必須記錄起來。這部分的存儲順序會受到虛擬機分配策略參數(-XX: FieldsAllocationStyle) 和欄位在Java源碼中定義順序的影響。

對齊填充

對齊填充並不是必然存在的,也沒有特別的含義,僅僅只是起著占位符的作用,由於HotSpot VM的自動記憶體管理系統要求對象起始地址必須是8位元組的整數倍,就是對象的大小必須是8位元組的整數倍,而對象頭部分正好是8位元組的倍數(1倍或者2倍),因此,當對象實例數據部分沒有對齊時,就需要通過對齊填充來補全。

原子性

synchronized實現原子性底層是通過JVM來實現的,同一時間只能有一個線程去執行synchronized中的代碼塊;
每一個對象都有一個監視器monitor來關聯,監視器被占用時會被鎖住,其他線程無法獲取該monitor,當JVM執行某個線程的的內部方法的monitorenter,它會嘗試去獲取該對象的monitor的所有權,過程如下
1、若monitor的進入數為0,線程可以進入monitor,並將該monitor的進入數置為1,那麼該線程就成為monitor的所有者
2、若線程已擁有monitor的所有權,允許它重入monitor,則進入monitor的進入數加1(recursions:記錄線程擁有鎖的次數)
3、若其他線程已經占有monitor的所有權,那麼當前嘗試獲取monitor的所有權的線程會被阻塞,直到monitor的進入數變為0,才能重新嘗試獲取monitor的所有權。
monitorexit指令
1、能執行monitorexit指令的線程一定是擁有當前對象的monitor的所有權的線程。
2、當執行monitorexit時會將monitor的進入數減1。當monitor的進入數減為0時,當前線程退出monitor,不再擁有monitor的所有權,此時這個monitor阻塞的線程可以嘗試去獲取這個monitor的所有權。

可見性

synchronized通過記憶體屏障保證可見性,同樣的我們知道volatile是通過記憶體屏障來保證可見性的,
1、monitorenter指令之後,synchronized內部的共用變數,每次讀取數據的時候被強制從主記憶體讀取最新的數據。
2、monitorexit指令也具有Store屏障的作用,也就是讓synchronized代碼塊內的共用變數,如果數據有變更的,強制刷新回主記憶體。
數據修改之後立即刷新回主記憶體,其他線程進入synchronized代碼塊後,使用共用變數的時候強制讀取主記憶體的數據。

有序性

同樣的,synchronized也是通過monitorenter、monitorexit指令嵌入上面的記憶體屏障,既具有加鎖、釋放鎖的功能,同時也具有記憶體屏障的功能


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • """python的拆包和封包之 *號在函數形參和實參的區別1. 在函數形參定義時添加*就是封包過程,封包預設是以元組形式進行封包2. 在函數實參調用過程添加*就是拆包過程,拆包過程中會報列表或者元組拆成單個元素"""subject = ["math", "chinese", 'english', ...
  • 剛剛看到一篇博客,說 stdbind 無法綁定正確的重載函數。這裡的問題並不是 stdbind 能力不足,而是將函數名傳遞給 std::bind 時編譯器無法取到這個函數的地址(也就是符號,編譯器會先解析成符號,鏈接器再替換為地址),因為有多個重載函數都是這個名字。核心問題是無法通過函數名取到想要的 ...
  • Spring Ioc源碼分析系列--自動註入迴圈依賴的處理 前言 前面的文章Spring Ioc源碼分析系列--Bean實例化過程(二)在講解到Spring創建bean出現迴圈依賴的時候並沒有深入去分析了,而是留到了這一篇去分析。為什麼要另起一篇,首先迴圈依賴是個很經典的問題,也是面試屢屢被問到的問 ...
  • 作者:lex-wu 來源:www.cnblogs.com/lex-wu/p/14610110.html 前言 最初是覺得我們打工人,在歷史的浪潮中,我們都被推著上岸。電子產品和移動互聯網,把我們的生活節奏大大提速了,所以很多人都忘記了生活和工作中的關係。 所以在深圳這個城市的各個街道上,都能看到忙忙 ...
  • 整型是我們日常生活中最常用到的基礎數據類型,看這篇文章之前,我想問: 我們真的像自己認為的那麼理解 Java 內的整型嗎? 也許看完本篇文章你就有自己的答案。 C 語言 提供瞭如下的整型 學習 Java 的整型之前,讓我們看看它的前輩——C 語言的實現。 讓我們更好地瞭解它的設計。 數據類型 占用字 ...
  • 成交量(volume)是投資中一個非常重要的變數,它是指在某一時段內具體的交易數,可以在分時圖中繪製,包括日線圖、周線圖、月線圖甚至是5分鐘、30分鐘、60分鐘圖中繪製。 股票市場成交量的變化反映了資金進出市場的情況,成交量是判斷市場走勢的重要指標。一般情況下,成交量大且價格上漲的股票,趨勢向好。成 ...
  • 有時候,我們將數據變換之後再繪圖,一方面,可以突出某些區域的數據;另一方面,變換之後可以更好的看出數據之間的關係。 matplotlib 提供了兩種變換數據的方式,一種是 Scale(縮放),一種是Projection(投影)。 Scale是對數據的一個維度進行變換,Projection則是對2個或 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...