Java 關鍵字:synchronized詳解

synchronized詳解

  • 基本使用
  • 源碼解析
  • 常見面試題
  • 好書推薦

基本使用

在這里插入圖片描述

Java中的synchronized關鍵字用于在多線程環境下確保數據同步。它可以用來修飾方法和代碼塊
當一個線程訪問一個對象的synchronized方法或代碼塊時,其他線程將無法訪問該對象的其他synchronized方法或代碼塊。這樣可以確保在同一時間只有一個線程能夠執行該代碼塊或方法,避免了多線程環境下的數據不一致問題,例如:

public class SynchronizedExample {private int count = 0;public synchronized void increment() {count++;}
}

在上面的代碼中,increment()方法是一個synchronized方法。當多個線程訪問這個方法時,只有一個線程能夠執行該方法的代碼,其他線程將被阻塞。
synchronized關鍵字也可以用來修飾代碼塊,如:

public void increment() {synchronized(this) {count++;}
}

在上面的代碼中,synchronized關鍵字修飾的是一個代碼塊,并且鎖對象是當前對象(this)
注意:synchronized關鍵字會導致線程上下文切換和資源競爭,所以在使用時要注意性能問題

源碼解析

底層實現是通過 Java 虛擬機(JVM)的對象頭和監視器鎖機制實現的

具體來說,當一個線程訪問一個對象的 synchronized 方法或代碼塊時,它會試圖獲取該對象的監視器鎖。如果該鎖未被其他線程占用,該線程將獲得該鎖并執行代碼;如果該鎖被其他線程占用,該線程將進入阻塞狀態,等待獲取該鎖

synchronized 是Java中用于實現同步的關鍵字,它在底層通過監視器鎖(Monitor)來實現。下面是synchronized的源碼解析:

在Java中,每個對象都有一個與之關聯的監視器鎖,也稱為內置鎖或對象鎖。當線程進入一個synchronized方法或代碼塊時,它會嘗試獲取該對象的監視器鎖。如果鎖沒有被其他線程占用,則該線程獲得鎖并開始執行代碼;如果鎖已經被其他線程占用,則該線程將被阻塞,直到鎖被釋放。

在Java虛擬機中,每個對象頭中都包含一部分用于實現synchronized的相關信息。這些信息包括:

  • mark word:用于存儲對象的標記信息,包括鎖的狀態。
  • Klass pointer:指向對象的類元數據,包括synchronized的相關信息。
  • monitor:與對象關聯的監視器,它記錄了當前占用鎖的線程、等待鎖的線程隊列等。

當一個線程嘗試獲取一個對象的鎖時,虛擬機會檢查對象頭中的標記信息。如果對象的鎖狀態為無鎖狀態,即未被其他線程占用,則該線程可以獲取鎖,并將標記信息設置為鎖定狀態。如果對象的鎖狀態為已鎖定,并且當前線程是鎖的所有者,則該線程可以繼續執行代碼。如果對象的鎖狀態為已鎖定,并且當前線程不是鎖的所有者,則該線程將被放入等待隊列中,進入阻塞狀態。

當持有鎖的線程執行完synchronized方法或代碼塊后,它會釋放鎖,即將對象頭中的鎖狀態置為無鎖狀態,并喚醒等待隊列中的一個線程,使其獲取鎖并繼續執行。

需要注意的是,synchronized關鍵字可以修飾方法和代碼塊。在方法上修飾的synchronized表示對整個方法進行同步,而在代碼塊上修飾的synchronized表示對該代碼塊進行同步,使用的鎖對象通常是方法所屬對象或指定的對象。

總結起來,通過監視器鎖的機制,Java的synchronized能夠保證同一時刻只有一個線程訪問同步代碼塊或方法,避免了多線程的數據競爭和并發問題。

這里給出一份簡化的 synchronized 關鍵字的源碼:

public void synchronized method() {// 加鎖Monitor.enter(this);try {// 同步代碼塊} finally {// 釋放鎖Monitor.exit(this);}
}

在這份代碼中,方法通過調用 Monitor.enter 方法獲取當前對象的監視器鎖,并在 finally 塊中調用 Monitor.exit 方法釋放該鎖。因此,在 synchronized 方法內部的代碼可以保證在任意時刻只有一個線程可以訪問

常見面試題

  • synchronized 方法和 synchronized 塊的區別是什么?
    作用范圍:synchronized 方法將整個方法體作為同步區塊,而 synchronized 塊可以將任意代碼塊作為同步區塊
    鎖的對象:synchronized 方法鎖定的是整個對象,而 synchronized 塊鎖定的是在括號內指定的對象
    可控性:synchronized 方法的同步粒度比較大,不夠靈活;而 synchronized 塊可以更靈活地控制同步代碼塊的大小
    綜上所述,在確定同步粒度時,通常使用 synchronized 塊比使用 synchronized 方法更靈活,但是如果整個方法都需要同步,使用 synchronized 方法會更加簡單易懂
  • 什么情況下可以使用 synchronized 關鍵字?
    synchronized 關鍵字可以用于在多線程環境下保證方法或代碼塊的原子性。具體來說,如果一個線程正在執行同步方法或代碼塊,則其他線程將無法訪問該方法或代碼塊
    常見情況包括:
    當多個線程訪問共享資源時,可以使用 synchronized 關鍵字保證線程的安全
    在訪問共享變量時,需要對其進行同步控制
  • 在線程通信中,可以使用 synchronized 關鍵字保證線程之間的同步通信
    synchronized 關鍵字的性能開銷如何?
    synchronized 關鍵字的使用會帶來一些性能開銷,因為它需要在多個線程之間進行同步。當線程訪問同步代碼塊時,它必須獲得鎖,這會增加額外的開銷。如果同步代碼塊執行時間過長,其他線程將一直等待,進而降低程序的性能。
    因此,應該盡量避免在高并發情況下使用 synchronized,或者使用其他的并發控制機制,如 java.util.concurrent 包中的鎖和原子操作類等。
  • synchronized 關鍵字如何實現可重入?
    “可重入” 指的是同一線程可以多次獲取同一個鎖。例如,當線程 A 進入一個同步塊時,如果它再次試圖進入該塊,則可以再次獲取鎖,而不會發生死鎖
    在 Java 中,synchronized 關鍵字可以實現可重入,原因如下:
    synchronized 關鍵字使用對象監視器鎖來實現同步。
    對象監視器鎖是基于線程的,并且每個線程有一個獨立的計數器,用于跟蹤它在當前對象上獲取的鎖的數量。
    當線程試圖獲取鎖時,如果它已經擁有該鎖,則計數器將遞增。
    當線程退出同步塊時,計數器將遞減。
    只有當計數器為零時,該線程才會釋放鎖。
    因此,如果一個線程在同一對象上多次進入同步塊,它將多次獲得該鎖,并在退出該塊時多次釋放該鎖。因此,synchronized 關鍵字是可重入的。
  • synchronized 關鍵字與 lock 機制的比較?
    synchronized 關鍵字和 Lock 機制都是用來保證線程同步的方法。但是它們有一些明顯的差異:

靈活性:Lock 機制比 synchronized 關鍵字更靈活,因為它提供了更多的鎖定操作,例如可以實現公平鎖和非公平鎖,還可以實現讀寫鎖。
可中斷性:Lock 機制可以中斷一個線程的等待,而 synchronized 關鍵字不能。
可重入性:synchronized 關鍵字是自動可重入的,而 Lock 機制必須手動實現。
性能:如果比較的是相同的鎖定操作,synchronized 關鍵字通常比 Lock 機制更快,因為它是內置的。
總體而言,在簡單的同步情況下,synchronized 關鍵字更方便,但是在需要更多靈活性的情況下,Lock 機制可能是一個更好的選擇。

好書推薦

深入理解 Java 高并發編程

修煉高并發內功,面試求職常備。計算機、系統、軟件多層次講透CPU并發、內核并發、Java并發、線程池、JVM原理。

在這里插入圖片描述
購書鏈接:點擊傳送門

  • 內容簡介

《深入理解Java高并發編程》致力于介紹Java高并發編程方面的知識。由于多線程處理涉及的知識內容十分豐富,因此介紹時必須從Java層面的講解一直深入到底層的知識講解。為了幫助讀者輕松閱讀本書并掌握其中知識,本書做了大量基礎知識的鋪墊。在第1篇基礎知識儲備中,主要介紹計算機原理、并發基礎、常見語言的線程實現、Java并發入門、JUC之Java線程池、JUC之同步結構、Java NIO詳解等內容。在第2篇深入Java并發原理中,詳細介紹了JUC包中所有使用的原子類的原理與源碼實現;非常關鍵且容易出錯的volatile關鍵字的原理,從Java、JVM、C、匯編、CPU層面對其進行詳細講解;synchronized在JVM中獲取鎖和釋放鎖的流程;JUC包的核心結構——AQS的原理與源碼實現,通過逐方法、逐行的解釋,幫助讀者徹底掌握AQS中提供的獲取鎖、釋放鎖、條件變量等操作的實現與原理。最后,詳細介紹了JVM中JNI的實現原理,將Java Thread對象中的所有方法在JVM層面的實現流程進行了詳細描述,以幫助讀者在使用這些方法時,知道底層發生了什么,以及發生異常時如何從容解決問題。

  • 作者簡介

黃俊,專注于研究Java語言, Hotspot, Linux內核,C語言與匯編,架構設計,多線程并發處理,專注于研究高效學習方式。曾就職于美團、阿里,前新東方業務架構師。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/164661.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164661.shtml
英文地址,請注明出處:http://en.pswp.cn/news/164661.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【愚公系列】2023年11月 Java教學課程 188-SpringCloud(Feign遠程調用)

🏆 作者簡介,愚公搬代碼 🏆《頭銜》:華為云特約編輯,華為云云享專家,華為開發者專家,華為產品云測專家,CSDN博客專家,阿里云專家博主,阿里云簽約作者&#xf…

如何通過寶塔面板搭建一個本地MySQL數據庫服務并實現遠程訪問

寶塔安裝MySQL數據庫,并內網穿透實現公網遠程訪問 文章目錄 寶塔安裝MySQL數據庫,并內網穿透實現公網遠程訪問前言1.Mysql服務安裝2.創建數據庫3.安裝cpolar3.2 創建HTTP隧道 4.遠程連接5.固定TCP地址5.1 保留一個固定的公網TCP端口地址5.2 配置固定公網…

浙江師范黃昌勤老師關于情感分析的講座

回放:https://share.weiyun.com/Wvaw4OoY 收獲很大: 寫幾點, 1:小二聚焦 精細更有用 2:高產的秘訣就是 專注一個領域,不斷延展。 3:好的文章技術不是本質,本質還是解決了什么教育問…

九、ffmpeg命令轉封裝

開了幾天小差,今天繼續學習ffmpeg。 準備測試使用的視頻,并查看其信息 # 查看視頻信息。使用Mediainfo也可以 ffprobe test.mp4 視頻格式的信息如下。 保持編碼格式:ffmpeg -i test.mp4 -vcodec copy -acodec copy test_copy.tsffmpeg -i…

WordPress網站如何修復數千個帖子的SEO錯誤

在本教程中,我們將向您展示如何解決您經常犯的SEO錯誤。 最好的是您不必花費太多時間,因為您不需要打開并編輯每個帖子。 相反,我們將向您展示如何使用 WordPress 內的電子表格來修復 WordPress 帖子的 SEO。 在這里,我們為您提…

nint和Pattern matching介紹(C#)

nint 最近看C# 9.0時,發現一個有意思的關鍵詞,就是nint,第一次看到這個,于是好奇心爆棚,就去實際操作了一下。 nint i 1000; Console.WriteLine("i{0}", i);實際結果與int的結果是一樣的,那為什…

ARM裸機-19(NandFlash和iNand)

1、NandFlash的接口 1.1、Nand的型號與命名 (1)、Nand的型號命名都有含義,就拿K9F2G08來示例分析一下:K9F表示是三星公司的NandFlash系列。2G表示Nand的大小是2Gbit (256MB)。08表示Nand是8位的 (8位就是數據線有8根)。 (2)、Nand命名中可以看出&#x…

【2023.11.23】JDBC基本連接語法學習?

1.導入jar包依賴:mysql-connector-java-8.0.27.jar 2.連接數據庫! 3.無法解析類->導入java.sql.*,(將項目方言改為Mysql) JDBC,啟動!! public class Main {public static voi…

如何下載OpenJDK及其源碼

如果想下載 OpenJDK,存在以下幾種辦法: 最簡單的辦法是去 OpenJDK 官網,這里能下載 JDK9 及其以上的版本,還有 JDK 源碼所在的 github 地址。 第二種方法是使用 IDEA 下載,位置在 File->Project Structure->SD…

【Vue】核心特性(響應式)

響應式&#xff1a; 數據變化&#xff0c;視圖自動更新 接下來使用一個例子來體現一下什么是響應式 案例一&#xff1a; 訪問數據&#xff0c;視圖自動更新 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><…

【人生苦短,我學 Python】(1)初識 Python

目錄 1. 簡述2. 什么是 Python&#xff1f;3. 面向對象簡述3.1 面向過程3.2 面向對象3.3 面向對象的主要優點3.4 面向對象的基本概念3.5 面向對象程序設計 4. Python語言的版本和解釋器5. Python 編程工具6. Python 的三種編程方式7. 簡單的 Python 程序8. 高級一點的 Python 程…

數據通信與計算機網絡(精煉知識點)

前言 該部分知識點不多,分值3分 知識點 TCP TCP采用可變大小的滑動窗口協議進行流量控制。在前向糾錯系統中,當接收端檢測到錯誤后就根據糾錯編碼的規律自行糾錯;在后向糾錯系統中,接收方會請求發送方重發出錯分組。IP協議不預先建立虛電路,而是對每個數據報獨立地選擇…

Linux快速顯示文件行號并跳轉

有時候&#xff0c;想要在線上直接查看日志文件&#xff0c;搜索到關鍵詞后&#xff0c;如果一直按n找下去&#xff0c;很麻煩&#xff0c;我們可以先顯示出行號&#xff0c;確定好我們要找內容對應的行號&#xff0c;直接跳轉過去。 esc進入命令模式&#xff0c;輸入:set nu命…

Cesium:CGCS2000坐標和WGS84坐標互相轉換

作者:CSDN @ _樂多_ 本文記錄了CGCS2000坐標和WGS84經緯度互相轉換的js代碼。封裝成了函數。 文章目錄 一、WGS84ToCGCS2000二、CGCS2000ToWGS84一、WGS84ToCGCS2000 import proj4 from "proj4";convertWGS84ToCGCS2000(wgs84X, wgs84Y, wgs84Z)

Amlogic方案遙控器配置(Android11)

配置路線 鍵值變化路徑&#xff1a; ScanCode --> Keycode Lable --> KeyCode Layout --> KeyLable --> Keycode – > KeyEvent 文件映射路徑&#xff1a; *.dtsi --> input-event-codes.h --> *.kl --> InputEventLable.h --> kecodes.h --> P…

通過這個簡單的技巧讓我們的 JavaScript 代碼變得異常快

通過這個簡單的技巧讓我們的 JavaScript 代碼變得異常快 秘訣&#xff1a;了解JavaScript 虛擬機(VM)的內部工作原理。 首先&#xff0c;我們來談談像 V8 這樣的JavaScript 虛擬機(VM)。可以把它想象成我們的操作的大腦 —— 它將我們簡潔的代碼變成計算機可以理解和執行的東…

免費圖書教材配套資料:Spark大數據技術與應用(第2版)

《Spark大數據技術與應用&#xff08;第2版&#xff09;》課程內容全面介紹了Spark大數據技術的相關知識&#xff0c;內容包含包括Spark概述、Scala基礎、Spark編程、Spark編程進階、Spark SQL結構化數據文件處理、Spark Streaming實時計算框架、Spark GraphX圖計算框架、Spark…

方法簽名【C#】

1條件&#xff1a; 簽名的作用&#xff1a;為了在眾多方法中找到匹配的方法。【自己想要的方法】類似明星的簽名。雖然2個人的名字一樣&#xff0c;但并不是同一個人&#xff0c;這就需要用到簽名的條件。 方法名稱&#xff1a;注意大小寫。 參數個數。 參數類型及順序&…

STL—next_permutation函數

目錄 1.next_permutation函數的定義 2.簡單使用 2.1普通數組全排列 2.2結構體全排列 2.3string 3.補充 1.next_permutation函數的定義 next_permutation函數會按照字母表順序生成給定序列的下一個較大的排列&#xff0c;直到整個序列為降序為止。與其相對的還有一個函數—…

實用工具推薦 | 在線制作電子書

?隨著互聯網的發展&#xff0c;越來越多的人開始關注知識的傳播和分享。而電子書作為一種方便攜帶、易于分享的形式&#xff0c;越來越受到人們的青睞。今天&#xff0c;就為大家推薦一款實用的工具——FLBOOK在線制作電子雜志平臺&#xff0c;讓你輕松在線制作電子書&#xf…