日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

java synchronized关键字_Java:手把手教你全面学习神秘的Synchronized关键字

發布時間:2025/3/20 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java synchronized关键字_Java:手把手教你全面学习神秘的Synchronized关键字 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

在Java中,有一個常被忽略 但 非常重要的關鍵字Synchronized

今天,我將詳細講解 Java關鍵字Synchronized的所有知識,希望你們會喜歡

目錄

示意圖

1. 定義

Java中的1個關鍵字

2. 作用

保證同一時刻最多只有1個線程執行 被Synchronized修飾的方法 / 代碼

其他線程 必須等待當前線程執行完該方法 / 代碼塊后才能執行該方法 / 代碼塊

3. 應用場景

保證線程安全,解決多線程中的并發同步問題(實現的是阻塞型并發),具體場景如下:

修飾 實例方法 / 代碼塊時,(同步)保護的是同一個對象方法的調用 & 當前實例對象

修飾 靜態方法 / 代碼塊時,(同步)保護的是 靜態方法的調用 & class 類對象

4. 原理

依賴 JVM 實現同步

底層通過一個監視器對象(monitor)完成, wait()、notify() 等方法也依賴于 monitor 對象

監視器鎖(monitor)的本質 依賴于 底層操作系統的互斥鎖(Mutex Lock)實現

5. 具體使用

Synchronized 用于 修飾 代碼塊、類的實例方法 & 靜態方法

5.1 使用規則

示意圖

5.2 鎖的類型 & 等級

由于Synchronized 會修飾 代碼塊、類的實例方法 & 靜態方法,故分為不同鎖的類型

具體如下

示意圖

之間的區別

示意圖

5.3 使用方式

/**

* 對象鎖

*/

public class Test{

// 對象鎖:形式1(方法鎖)

public synchronized void Method1(){

System.out.println("我是對象鎖也是方法鎖");

try{

Thread.sleep(500);

} catch (InterruptedException e){

e.printStackTrace();

}

}

// 對象鎖:形式2(代碼塊形式)

public void Method2(){

synchronized (this){

System.out.println("我是對象鎖");

try{

Thread.sleep(500);

} catch (InterruptedException e){

e.printStackTrace();

}

}

}

/**

* 方法鎖(即對象鎖中的形式1)

*/

public synchronized void Method1(){

System.out.println("我是對象鎖也是方法鎖");

try{

Thread.sleep(500);

} catch (InterruptedException e){

e.printStackTrace();

}

}

/**

* 類鎖

*/

public class Test{

// 類鎖:形式1 :鎖靜態方法

public static synchronized void Method1(){

System.out.println("我是類鎖一號");

try{

Thread.sleep(500);

} catch (InterruptedException e){

e.printStackTrace();

}

}

// 類鎖:形式2 :鎖靜態代碼塊

public void Method2(){

synchronized (Test.class){

System.out.println("我是類鎖二號");

try{

Thread.sleep(500);

} catch (InterruptedException e){

e.printStackTrace();

}

}

}

5.4 特別注意

Synchronized修飾方法時存在缺陷:若修飾1個大的方法,將會大大影響效率

示例

若使用Synchronized關鍵字修飾 線程類的run(),由于run()在線程的整個生命期內一直在運行,因此將導致它對本類任何Synchronized方法的調用都永遠不會成功

解決方案

使用 Synchronized關鍵字聲明代碼塊

該解決方案靈活性高:可針對任意代碼塊 & 任意指定上鎖的對象

代碼如下

synchronized(syncObject) {

// 訪問或修改被鎖保護的共享狀態

// 上述方法 必須 獲得對象 syncObject(類實例或類)的鎖

}

6. 特點

示意圖

注:原子性、可見性、有序性的定義

示意圖

7. 其他控制并發 / 線程同步方式

7.1 Lock、ReentrantLock

簡介

示意圖

區別

示意圖

7.2 CAS

7.2.1 定義

Compare And Swap,即 比較 并 交換,是一種解決并發操作的樂觀鎖

synchronized鎖住的代碼塊:同一時刻只能由一個線程訪問,屬于悲觀鎖

7.2.2 原理

// CAS的操作參數

內存位置(A)

預期原值(B)

預期新值(C)

// 使用CAS解決并發的原理:

// 1. 首先比較A、B,若相等,則更新A中的值為C、返回True;若不相等,則返回false;

// 2. 通過死循環,以不斷嘗試嘗試更新的方式實現并發

// 偽代碼如下

public boolean compareAndSwap(long memoryA, int oldB, int newC){

if(memoryA.get() == oldB){

memoryA.set(newC);

return true;

}

return false;

}

7.2.3 優點

資源耗費少:相對于synchronized,省去了掛起線程、恢復線程的開銷

但,若遲遲得不到更新,死循環對CPU資源也是一種浪費

7.2.4 具體實現方式

使用CAS有個“先檢查后執行”的操作

而這種操作在Java中是典型的不安全的操作,所以 CAS在實際中是由C++通過調用CPU指令實現的

具體過程

// 1. CAS在Java中的體現為Unsafe類

// 2. Unsafe類會通過C++直接獲取到屬性的內存地址

// 3. 接下來CAS由C++的Atomic::cmpxchg系列方法實現

7.2.5 典型應用:AtomicInteger

對 i++ 與 i--,通過compareAndSet & 一個死循環實現

而compareAndSet函數內部 = 通過jni操作CAS指令。直到CAS操作成功跳出循環

private volatile int value;

/**

* Gets the current value.

*

* @return the current value

*/

public final int get() {

return value;

}

/**

* Atomically increments by one the current value.

*

* @return the previous value

*/

public final int getAndIncrement() {

for (;;) {

int current = get();

int next = current + 1;

if (compareAndSet(current, next))

return current;

}

}

/**

* Atomically decrements by one the current value.

*

* @return the previous value

*/

public final int getAndDecrement() {

for (;;) {

int current = get();

int next = current - 1;

if (compareAndSet(current, next))

return current;

}

}

8. 總結

本文主要對Java中常被忽略 但 非常重要的關鍵字Synchronized進行講解

下面我將繼續對 Android & Java中的知識進行深入講解 ,感興趣的同學可以繼續關注本人運營的Wechat Public Account:

請點贊!因為你的鼓勵是我寫作的最大動力!

不定期分享關于安卓開發的干貨,追求短、平、快,但卻不缺深度。

總結

以上是生活随笔為你收集整理的java synchronized关键字_Java:手把手教你全面学习神秘的Synchronized关键字的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。