JAVA鎖機制:對象鎖與類鎖

JAVA鎖機制:對象鎖與類鎖

在多線程編程中,合理使用鎖機制是保證數據一致性和線程安全的關鍵。本文將通過示例詳細講解 Java 中的對象鎖和類鎖的原理、用法及區別。

一、未加鎖的并發問題

先看一段未加鎖的代碼:

public class SynchronizedTest {private int shareField = 0;public void add() {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}public static void main(String[] args) {SynchronizedTest sync = new SynchronizedTest();new Thread(() -> {for (int n = 0; n < 100000; n++) {sync.add();}}).start();new Thread(() -> {for (int n = 0; n < 100000; n++) {sync.add();}}).start();}
}

上述代碼啟動兩個線程,每個線程各自循環10萬次,對 shareField 進行自增。理論上,最終 shareField 應為 200000,但實際運行結果往往小于 200000:

當前線程:Thread-0 當前的shareField為:199994
當前線程:Thread-0 當前的shareField為:199995
...

原因在于多個線程并發修改同一變量,導致數據競爭。


二、對象鎖

對象鎖用于保護同一個實例的資源,確保同一時刻只有一個線程能訪問被鎖定的代碼塊。

1. 鎖定非靜態方法

public class SynchronizedTest {private int shareField = 0;public synchronized void add() {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}// 省略 main 方法
}

synchronized 修飾非靜態方法時,鎖的是當前實例對象 (this)。

2. 鎖定 this 對象(代碼塊)

有時只需對方法中的部分代碼加鎖,可以使用同步代碼塊:

public void add() {synchronized (this) {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}
}

3. 鎖定特定對象

也可以指定其他對象作為鎖:

private final Object obj = new Object();
public void add() {synchronized (obj) {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}
}
對象鎖特點
  • 鎖對象:當前實例(this)或指定對象
  • 多線程訪問同一實例的同步方法時互斥
  • 不同實例之間互不影響

三、類鎖

類鎖用于保護類級別的資源(如靜態變量),確保同一時刻只有一個線程能訪問被鎖定的靜態資源。

1. 鎖定靜態方法

public static synchronized void add() {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);
}

synchronized 修飾靜態方法時,鎖的是類的 Class 對象。

2. 鎖定 class 對象

public void add() {synchronized (SynchronizedTest.class) {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}
}

3. 鎖定靜態實例變量

private static final Object obj = new Object();
public void add() {synchronized (obj) {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}
}
類鎖特點
  • 鎖對象:類的 Class 對象或靜態實例變量
  • 所有實例共享同一把鎖,實現全局互斥

四、對象鎖與類鎖的區別

選擇對象鎖還是類鎖,取決于需要保護的變量是實例級還是類級(靜態)。

例如:

public class SynchronizedTest {private static int shareField = 0;public void add() {synchronized (this) {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}}public static void main(String[] args) {new Thread(() -> {SynchronizedTest sync1 = new SynchronizedTest();for (int n = 0; n < 100000; n++) {sync1.add();}}).start();new Thread(() -> {SynchronizedTest sync2 = new SynchronizedTest();for (int n = 0; n < 100000; n++) {sync2.add();}}).start();}
}

上述代碼中,兩個線程分別操作不同實例,但都修改靜態變量 shareField。此時對象鎖無法保證線程安全,需使用類鎖:

public void add() {synchronized (SynchronizedTest.class) {shareField++;System.out.println("當前線程:" + Thread.currentThread().getName() + " 當前的shareField為:" + shareField);}
}

五、總結

特性對象鎖類鎖
鎖對象當前實例(this)/obj類的Class對象/靜態實例變量
作用范圍同一實例間互斥所有實例間互斥
適用場景保護實例級變量保護類級變量(靜態變量)
并發影響不同實例間無互斥所有實例共享同一把鎖
實現方式synchronized方法/代碼塊static synchronized方法/class鎖對象

合理選擇鎖的類型,是實現高效并發和線程安全的關鍵。

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

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

相關文章

maxcomputer 和 hologres中的EXTERNAL TABLE 和 FOREIGN TABLE

在阿里云的大數據和實時數倉產品中&#xff0c;MaxCompute 和 Hologres 都支持類似于 EXTERNAL TABLE 和 FOREIGN TABLE 的機制&#xff0c;但它們的實現和語義有所不同。 下面分別說明&#xff1a; ?? 一、MaxCompute 中的 EXTERNAL TABLE 和 FOREIGN TABLE 1. EXTERNAL T…

穩定幣:從支付工具到金融基礎設施的技術演進與全球競爭新格局

引言&#xff1a;穩定幣的崛起與金融體系重構 2025年6月&#xff0c;全球穩定幣市值突破2500億美元歷史大關&#xff0c;單年鏈上交易額高達35萬億美元——這一數字已超越Visa和萬事達卡交易總和。這一里程碑事件標志著穩定幣已從加密貨幣市場的邊緣實驗&#xff0c;蛻變為重構…

用 HTML、CSS 和 jQuery 打造多頁輸入框驗證功能

多頁輸入框驗證功能總結:使用 HTML、CSS 和 jQuery 實現 一、多頁表單驗證的核心概念與應用場景 多頁輸入框驗證是指將復雜表單拆分為多個頁面或步驟,逐步引導用戶完成輸入,并在每一步對用戶輸入進行驗證的功能。這種設計具有以下優勢: 提升用戶體驗:避免長表單帶來的心…

DeepSpeed 深度學習學習筆記:高效訓練大型模型

主要參考官網文檔&#xff0c;對于具體內容還需參考官方文檔 1. 引言&#xff1a;為什么需要 DeepSpeed&#xff1f; 大型模型訓練的挑戰 隨著深度學習模型規模的爆炸式增長&#xff08;從 BERT 的幾億參數到 GPT-3 的千億參數&#xff0c;再到現在的萬億參數模型&#xff09…

編程基礎:耦合

能幫到你的話&#xff0c;就給個贊吧 &#x1f618; 文章目錄 耦合&#xff1a;功能的單一性&#xff0c;功能越拆分則單一功能越好維護 耦合&#xff1a;功能的單一性&#xff0c;功能越拆分則單一功能越好維護

基于Qt的UDP主從服務器設計與實現

概述 一個基于Qt框架實現的UDP主從服務器系統&#xff0c;該系統具備自動主機選舉、故障轉移和狀態同步等關鍵功能&#xff0c;適用于分布式能源管理系統中的設備通信與協調。 系統核心功能 1. 自動主機選舉與故障轉移 系統通過優先級機制實現自動主機選舉&#xff0c;當主機…

【51單片機2位數碼管100毫秒的9.9秒表】2022-5-16

緣由 這一題剛設計好要去回復就看到結帖了&#xff0c;好似看到我設計完成就盜竊去了&#xff0c;如此下面類似題目很容易也懶得回復了。 #include "reg52.h" sbit k0P3^0; sbit k1P3^1; unsigned char code SmZiFu[]{63,6,91,79,102,109,125,7,127,111};//0-9 uns…

安裝ClickHouse

安裝ClickHouse ClickHouse是一個用于聯機分析的列式數據庫管理系統&#xff0c;主要用于在線分析處理查詢&#xff08;OLAP&#xff09;&#xff0c;能夠使用SQL查詢實時生成分析數據報告。 ClickHouse是一個完全的列式數據庫管理系統&#xff0c;允許在運行時創建表和數據庫&…

PX4無人機集成自帶的深度相機進行gazebo仿真

修改mavros_posix_sitl.launch文件 修改以下兩行代碼 <arg name"my_model" default"iris_depth_camera"/><arg name"sdf" default"$(find mavlink_sitl_gazebo)/models/$(arg my_model)/$(arg my_model).sdf"/>iris_dept…

正點原子STM32cubeide學習——TFTLCD(MCU 屏)實驗

使用的是正點原子的精英版&#xff0c;單片機是STM32F103ZET6&#xff0c;使用開發板的 MCU 屏接口連接正點原子 TFTLCD 模塊(僅限 MCU 屏模塊)&#xff0c;實現 TFTLCD 模塊的顯示。通過把 LCD 模塊插入底板上的 TFTLCD 模塊接口&#xff0c;按下復位之后&#xff0c; 就可以看…

OpenCV實現二值圖細化(骨架提取)

對二值圖進行細化&#xff08;骨架提取&#xff09;&#xff0c;也就是把每根線條細化到一個像素的寬度。有兩個比較成熟的算法實現此功能&#xff0c;分別是Zhang-Suen算法和Guo-Hall算法。 我們下面使用OpenCVSharp&#xff0c;使用C#實現上述兩個算法&#xff1a; private…

歷史的迷霧與傳承的使命:應對歷史篡改,守護中華文明

在歷史的浩瀚長河中&#xff0c;中國以悠久的文明與燦爛的文化屹立于世界東方。然而&#xff0c;滿清時期與西方勢力出于各自目的對中國歷史進行篡改&#xff0c;在真實歷史的畫卷上蒙上了層層迷霧。深入探究其背后的動機&#xff0c;思考當代人守護歷史文化的使命&#xff0c;…

【Qt】QTableWidget表格右鍵菜單

效果 1. 給QTableWidget組件添加customContextMenuRequested信號 2. 槽函數 void dataDetailForm::on_tableWidget_customContextMenuRequested(const QPoint &pos) {QMenu menu;QAction *setEnd menu.addAction(tr("設置"));connect(setEnd, SIGNAL(triggered…

MySQL 數據處理函數全面詳解

MySQL 數據處理函數全面詳解 MySQL 中的數據處理函數,包含字符串、數值、日期、條件判斷等核心函數: 一、字符串處理函數 1. 基礎操作函數 函數描述示例結果CONCAT()字符串連接CONCAT(My,SQL)‘MySQL’CONCAT_WS()帶分隔符連接CONCAT_WS(-,2023,08,15)‘2023-08-15’LENGTH…

領域驅動設計(DDD)【1】之初步理解

文章目錄 一 DDD概述二 從“沉寂”到“爆火”&#xff1a;DDD的興起背景與原因2.1 DDD早期沉寂的原因2.2 DDD近年爆火的原因2.3 總結 三 DDD深入理解3.1 方法論本質3.2 系統化價值3.3 思想內核3.4 實踐轉化3.5 總結 四 傳統面向對象方法學和DDD4.1 傳統面向對象方法學的問題4.2…

人工智能學習57-TF訓練

人工智能學習概述—快手視頻 人工智能學習57-TF訓練—快手視頻 人工智能學習58-TF訓練—快手視頻 人工智能學習59-TF預測—快手視頻 訓練示例代碼 #導入keras.utils 工具包 import keras.utils #導入mnist數據集 from keras.datasets import mnist #引入tensorflow 類庫 …

MySQL(83)如何設置密碼復雜度策略?

在 MySQL 中&#xff0c;可以通過配置密碼策略來設置密碼的復雜度要求。MySQL 提供了一些參數和插件來幫助管理員強制實施密碼復雜度策略&#xff0c;確保數據庫用戶使用強密碼。下面將詳細介紹如何設置密碼復雜度策略&#xff0c;并結合代碼示例進行說明。 1. 使用 validate_…

如何使用postman做接口自動化測試?

&#x1f345; 點擊文末小卡片&#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 本文適合已經掌握 Postman 基本用法的讀者&#xff0c;即對接口相關概念有一定了解、已經會使用Postman 進行模擬請求等基本操作。 工作環境與版本&#xff1a; …

面試-操作系統

用戶態和內核態的區別 內核態&#xff1a;在內核態下&#xff0c;CPU可以執行所有的指令和訪問所有的硬件資源。 用戶態&#xff1a;在用戶態下&#xff0c;CPU只能執行部分指令集&#xff0c;無法直接訪問硬件資源。 內核態的底層操作主要包括&#xff1a;內存管理、進程管理…

【基礎算法】二分(二分查找 + 二分答案)

文章目錄 一、二分查找1. 【案例】在排序數組中查找元素的第一個和最后一個位置 ?(1) 二分查找的引入(2) 解題細節&#xff08;important&#xff09;(3) 代碼示例(4) 【模板】二分查找(5) STL 中的二分查找 2. 牛可樂和封印魔法 ??(1) 解題思路(2) 代碼實現 3. A-B 數對 ?…