Java synchronized關(guān)鍵字從入門(mén)到原理解析

適用對(duì)象
本課程適合具備Java基礎(chǔ)語(yǔ)法知識(shí),初步了解多線程概念但尚未系統(tǒng)學(xué)習(xí)并發(fā)編程的開(kāi)發(fā)者。無(wú)論你是準(zhǔn)備面試的求職者,還是希望提升并發(fā)編程能力的工程師,這門(mén)課程都將為你打下堅(jiān)實(shí)基礎(chǔ)。
學(xué)習(xí)目標(biāo)
通過(guò)兩個(gè)課時(shí)的系統(tǒng)學(xué)習(xí),你將能夠:
- 掌握 synchronized的三種使用方式及其區(qū)別
- 理解 synchronized解決線程安全問(wèn)題的核心原理
- 剖析 synchronized底層的Monitor機(jī)制和鎖升級(jí)過(guò)程
- 區(qū)分 synchronized與volatile、ReentrantLock的適用場(chǎng)景
- 應(yīng)對(duì) 面試中關(guān)于synchronized的高頻問(wèn)題
課程安排
- 第一課時(shí)(約40分鐘):基礎(chǔ)概念、使用方式、特性詳解
- 第二課時(shí)(約50分鐘):底層原理、鎖升級(jí)機(jī)制、對(duì)比與實(shí)戰(zhàn)
第一課時(shí):synchronized基礎(chǔ)與使用
1.1 從一個(gè)線程安全問(wèn)題開(kāi)始
讓我們先看一個(gè)經(jīng)典問(wèn)題:兩個(gè)線程同時(shí)對(duì)共享變量執(zhí)行自增操作。
public class Counter {
private int count = 0;
public void increment() {
count++; // 不是原子操作!
}
public int getCount() {
return count;
}
}
// 測(cè)試代碼
public class Test {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) counter.increment();
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) counter.increment();
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("最終結(jié)果: " + counter.getCount()); // 期望20000,實(shí)際小于20000
}
}運(yùn)行結(jié)果:多次執(zhí)行,結(jié)果總是小于20000,有時(shí)甚至相差甚遠(yuǎn)。
問(wèn)題根源:count++看似一行代碼,但在JVM中分解為三條指令:
- 從主內(nèi)存讀取count到工作內(nèi)存(讀)
- 對(duì)count進(jìn)行加1操作(改)
- 將結(jié)果寫(xiě)回主內(nèi)存(寫(xiě))
當(dāng)兩個(gè)線程同時(shí)執(zhí)行這三步時(shí),可能發(fā)生交替執(zhí)行,導(dǎo)致最后寫(xiě)入的值覆蓋了之前的計(jì)算結(jié)果——這就是典型的競(jìng)態(tài)條件。
1.2 synchronized是什么?
synchronized是Java提供的一個(gè)關(guān)鍵字,譯為“同步”。它可以保證在同一時(shí)刻,最多只有一個(gè)線程執(zhí)行被它修飾的代碼段,從而解決并發(fā)環(huán)境下的線程安全問(wèn)題。
從專業(yè)角度說(shuō),synchronized實(shí)現(xiàn)了互斥訪問(wèn),它保證了三個(gè)關(guān)鍵特性:
| 特性 | 說(shuō)明 |
|---|---|
| 原子性 | 被保護(hù)的代碼塊要么全部執(zhí)行,要么完全不執(zhí)行,不會(huì)被打斷 |
| 可見(jiàn)性 | 一個(gè)線程修改共享變量后,其他線程能立即看到最新值 |
| 有序性 | 禁止編譯器和處理器對(duì)同步塊內(nèi)的代碼進(jìn)行指令重排序 |
1.3 初識(shí)synchronized的三種用法
synchronized的使用非常靈活,可以根據(jù)需要選擇不同的加鎖對(duì)象。下面我們通過(guò)三個(gè)典型場(chǎng)景來(lái)理解它們的區(qū)別。
1.3.1 修飾實(shí)例方法
public class SyncMethodDemo {
private int count = 0;
// synchronized修飾實(shí)例方法,鎖是當(dāng)前對(duì)象this
public synchronized void increment() {
count++;
}
}特點(diǎn):
- 鎖對(duì)象是調(diào)用該方法的實(shí)例對(duì)象(即this)
- 同一個(gè)對(duì)象的多個(gè)synchronized實(shí)例方法,共用同一把鎖
- 不同對(duì)象的方法互不干擾
示意圖:
線程A ──> obj1.increment() ──> 獲取obj1鎖 ──> 執(zhí)行 線程B ──> obj1.increment() ──> 等待obj1鎖 線程C ──> obj2.increment() ──> 獲取obj2鎖 ──> 執(zhí)行(與A不沖突)
1.3.2 修飾靜態(tài)方法
public class SyncStaticDemo {
private static int count = 0;
// synchronized修飾靜態(tài)方法,鎖是當(dāng)前類(lèi)的Class對(duì)象
public static synchronized void increment() {
count++;
}
}特點(diǎn):
- 鎖對(duì)象是當(dāng)前類(lèi)的Class對(duì)象(如SyncStaticDemo.class)
- 所有實(shí)例對(duì)象共享同一把類(lèi)鎖
- 靜態(tài)方法鎖與實(shí)例方法鎖互不干擾
思考題:如果一個(gè)類(lèi)既有synchronized靜態(tài)方法,又有synchronized實(shí)例方法,兩個(gè)線程分別調(diào)用它們,會(huì)互斥嗎?
- 答案:不會(huì)。因?yàn)橐粋€(gè)是類(lèi)鎖,一個(gè)是對(duì)象鎖,兩把不同的鎖。
1.3.3 修飾代碼塊
public class SyncBlockDemo {
private Object lock = new Object();
private int count = 0;
public void increment() {
// 同步代碼塊,鎖是指定的lock對(duì)象
synchronized (lock) {
count++;
}
}
public void decrement() {
// 也可以鎖this
synchronized (this) {
count--;
}
}
}特點(diǎn):
- 鎖對(duì)象可以任意指定,靈活性最高
- 可以精確控制同步范圍,提高并發(fā)性能
- 常用鎖對(duì)象:this、自定義鎖對(duì)象、類(lèi).class
1.4 深入理解鎖的范圍
1.4.1 三種鎖的對(duì)比表格
| 使用形式 | 鎖對(duì)象 | 作用范圍 | 典型應(yīng)用場(chǎng)景 |
|---|---|---|---|
| 修飾實(shí)例方法 | 當(dāng)前實(shí)例對(duì)象 | 單個(gè)實(shí)例內(nèi) | 保護(hù)實(shí)例變量 |
| 修飾靜態(tài)方法 | 當(dāng)前類(lèi)的Class對(duì)象 | 所有實(shí)例間 | 保護(hù)靜態(tài)變量 |
| 修飾代碼塊 | 指定的任意對(duì)象 | 代碼塊內(nèi) | 細(xì)粒度控制 |
1.4.2 常見(jiàn)面試題解析
問(wèn)題1:synchronized修飾代碼塊可以給類(lèi)加鎖嗎?
當(dāng)然可以!只要在括號(hào)內(nèi)傳入類(lèi)名.class即可。例如:
synchronized (SyncBlockDemo.class) {
// 這是類(lèi)鎖
}問(wèn)題2:構(gòu)造方法可以用synchronized修飾嗎?
不可以!Java語(yǔ)法規(guī)定構(gòu)造方法不能是同步的。實(shí)際上,構(gòu)造方法本身就是線程安全的,因?yàn)镴VM會(huì)保證在對(duì)象初始化完成前,其他線程無(wú)法訪問(wèn)該對(duì)象。
問(wèn)題3:靜態(tài)同步方法和非靜態(tài)同步方法同時(shí)調(diào)用會(huì)互斥嗎?
不會(huì)互斥。假設(shè)線程A調(diào)用實(shí)例對(duì)象的非靜態(tài)同步方法,線程B同時(shí)調(diào)用該對(duì)象所屬類(lèi)的靜態(tài)同步方法,它們持有的是兩把不同的鎖(對(duì)象鎖 vs 類(lèi)鎖),因此可以并行執(zhí)行。
1.5 synchronized的核心特性
1.5.1 可重入性
概念:同一個(gè)線程在持有鎖的情況下,可以再次獲取同一把鎖,而不會(huì)被阻塞。
public class ReentrantDemo {
public synchronized void methodA() {
System.out.println("進(jìn)入methodA");
methodB(); // 直接調(diào)用,不會(huì)死鎖
}
public synchronized void methodB() {
System.out.println("進(jìn)入methodB");
}
}為什么需要可重入?
如果沒(méi)有可重入性,線程在調(diào)用methodA獲取鎖后,調(diào)用methodB時(shí)發(fā)現(xiàn)自己還要申請(qǐng)同一把鎖,就會(huì)形成死鎖。這顯然不合理。
實(shí)現(xiàn)原理:每個(gè)鎖關(guān)聯(lián)一個(gè)持有線程和一個(gè)計(jì)數(shù)器。線程第一次獲取鎖時(shí),計(jì)數(shù)器置為1;同一線程再次獲取時(shí),計(jì)數(shù)器遞增;釋放一次,計(jì)數(shù)器遞減。直到計(jì)數(shù)器歸零,鎖才真正釋放。
1.5.2 可見(jiàn)性保證
synchronized不僅能保證原子性,還能保證內(nèi)存可見(jiàn)性。JMM(Java內(nèi)存模型)規(guī)定:
- 線程釋放鎖時(shí),會(huì)將工作內(nèi)存中的共享變量刷新到主內(nèi)存
- 線程獲取鎖時(shí),會(huì)清空工作內(nèi)存,從主內(nèi)存重新讀取共享變量
這就確保了:一個(gè)線程修改的共享變量,在釋放鎖后,其他線程能立即看到最新值。
1.6 第一課時(shí)小結(jié)
- synchronized是Java內(nèi)置的同步關(guān)鍵字,解決原子性、可見(jiàn)性、有序性問(wèn)題
- 三種使用方式:實(shí)例方法(鎖this)、靜態(tài)方法(鎖Class對(duì)象)、代碼塊(鎖任意對(duì)象)
- 核心特性:可重入性、可見(jiàn)性、互斥性
- 不同鎖對(duì)象決定了不同的同步范圍
第二課時(shí):synchronized原理與優(yōu)化
2.1 從字節(jié)碼看synchronized的本質(zhì)
2.1.1 同步代碼塊的字節(jié)碼
先看一段簡(jiǎn)單的同步代碼塊:
public class SyncCodeBlock {
public void doSomething() {
synchronized (this) {
System.out.println("hello");
}
}
}使用javap -c -v反編譯后,關(guān)鍵字節(jié)碼如下:
3: monitorenter // 進(jìn)入同步塊,獲取監(jiān)視器鎖 4: getstatic // 調(diào)用System.out 7: ldc // 加載字符串 9: invokevirtual // 調(diào)用println 12: aload_1 13: monitorexit // 退出同步塊,釋放監(jiān)視器鎖 14: goto 22 // 正常結(jié)束跳轉(zhuǎn) 17: astore_2 // 異常處理開(kāi)始 18: aload_1 19: monitorexit // 異常時(shí)也釋放鎖 20: aload_2 21: athrow // 拋出異常 22: return
關(guān)鍵發(fā)現(xiàn):
- 同步代碼塊使用
monitorenter和monitorexit指令 - 有兩個(gè)
monitorexit:一個(gè)正常退出,一個(gè)異常退出,確保鎖一定被釋放 - 這就是為什么synchronized即使拋出異常也不會(huì)死鎖
2.1.2 同步方法的字節(jié)碼
public synchronized void syncMethod() {
System.out.println("hello");
}反編譯結(jié)果:
public synchronized void syncMethod(); descriptor: ()V flags: ACC_PUBLIC, ACC_SYNCHRONIZED // 注意這個(gè)標(biāo)志 Code: 0: getstatic #2 3: ldc #3 5: invokevirtual #4 8: return
同步方法沒(méi)有monitorenter/monitorexit指令,而是通過(guò)方法表flags中的ACC_SYNCHRONIZED標(biāo)識(shí)。JVM根據(jù)這個(gè)標(biāo)識(shí)判斷是否需要獲取鎖。
結(jié)論:兩種實(shí)現(xiàn)方式本質(zhì)上都是獲取對(duì)象的監(jiān)視器鎖(Monitor Lock),只是表現(xiàn)形式不同。
2.2 Monitor機(jī)制深度剖析
2.2.1 什么是Monitor?
Monitor(監(jiān)視器)是操作系統(tǒng)中用于實(shí)現(xiàn)線程同步的機(jī)制。Java中的每個(gè)對(duì)象都與一個(gè)Monitor關(guān)聯(lián),這個(gè)關(guān)聯(lián)關(guān)系存儲(chǔ)在對(duì)象頭的Mark Word中。
可以把Monitor理解為一個(gè)“接待室”,里面有三個(gè)關(guān)鍵區(qū)域:
┌─────────────────────┐
│ Owner │ ← 當(dāng)前持有鎖的線程
├─────────────────────┤
│ EntryList │ ← 等待獲取鎖的線程隊(duì)列
├─────────────────────┤
│ WaitSet │ ← 調(diào)用了wait()的線程隊(duì)列
└─────────────────────┘2.2.2 Monitor的核心數(shù)據(jù)結(jié)構(gòu)
在HotSpot虛擬機(jī)中,Monitor由C++的ObjectMonitor類(lèi)實(shí)現(xiàn),關(guān)鍵字段如下:
| 字段 | 作用 |
|---|---|
_owner | 指向當(dāng)前持有鎖的線程 |
_EntryList | 等待獲取鎖的線程隊(duì)列 |
_WaitSet | 調(diào)用了wait()的線程隊(duì)列 |
_recursions | 記錄鎖的重入次數(shù) |
_count | 記錄線程獲取鎖的次數(shù) |
2.2.3 鎖獲取和釋放的完整流程
以兩個(gè)線程T0和T1競(jìng)爭(zhēng)鎖為例:
步驟1:線程T0嘗試獲取鎖
- 根據(jù)對(duì)象頭找到對(duì)應(yīng)的ObjectMonitor
- 檢查
_owner是否為null - 通過(guò)CAS操作將
_owner設(shè)為T(mén)0,_count設(shè)為1 - T0獲取鎖成功,進(jìn)入同步塊執(zhí)行
步驟2:線程T1嘗試獲取鎖
- 此時(shí)
_owner為T(mén)0,T1 CAS失敗 - T1會(huì)先自旋幾次嘗試(適應(yīng)性自旋)
- 如果T0很快釋放鎖,T1就成功獲取
- 如果T0未釋放,T1進(jìn)入
_EntryList阻塞等待
步驟3:T0釋放鎖
- 執(zhí)行
monitorexit,_count減1 - 若
_count變?yōu)?,_owner設(shè)為null - 喚醒
_EntryList中的線程(通常是隊(duì)首線程) - T1被喚醒,重新競(jìng)爭(zhēng)鎖
2.3 鎖升級(jí):從偏向鎖到重量級(jí)鎖
早期Java的synchronized性能較差,被稱為“重量級(jí)鎖”。JDK 1.6之后引入了一系列優(yōu)化,讓synchronized的性能大幅提升。這就是著名的鎖升級(jí)機(jī)制。
2.3.1 為什么需要鎖升級(jí)?
想象一下這些場(chǎng)景:
- 場(chǎng)景A:只有一個(gè)線程訪問(wèn)同步代碼,根本不需要鎖競(jìng)爭(zhēng)
- 場(chǎng)景B:兩個(gè)線程交替訪問(wèn),幾乎沒(méi)有同時(shí)競(jìng)爭(zhēng)
- 場(chǎng)景C:多個(gè)線程激烈競(jìng)爭(zhēng),需要操作系統(tǒng)級(jí)別的鎖
如果用重量級(jí)鎖統(tǒng)一處理所有場(chǎng)景,場(chǎng)景A和B會(huì)造成不必要的性能開(kāi)銷(xiāo)。鎖升級(jí)就是讓synchronized能夠根據(jù)競(jìng)爭(zhēng)激烈程度,動(dòng)態(tài)調(diào)整鎖的“重量”。
2.3.2 鎖的四種狀態(tài)
從低到高,鎖有四種狀態(tài):
- 無(wú)鎖狀態(tài)
- 偏向鎖
- 輕量級(jí)鎖
- 重量級(jí)鎖
鎖可以升級(jí),但不能降級(jí)(除了一次GC清理)。
2.3.3 偏向鎖(Biased Locking)
適用場(chǎng)景:只有一個(gè)線程反復(fù)獲取同一把鎖。
原理:
- 第一次獲取鎖時(shí),通過(guò)CAS將線程ID記錄到對(duì)象頭
- 之后該線程再來(lái)時(shí),只需檢查對(duì)象頭中是否是自己ID
- 如果是,直接進(jìn)入,無(wú)需任何同步操作
示例代碼:
public class BiasedLockDemo {
private static List<Integer> list = new Vector<>(); // Vector的方法都是同步的
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
list.add(i); // 同一線程反復(fù)獲取鎖
}
}
}優(yōu)點(diǎn):幾乎沒(méi)有加鎖開(kāi)銷(xiāo),性能極高。
缺點(diǎn):一旦有其他線程嘗試競(jìng)爭(zhēng),偏向鎖立即撤銷(xiāo)并升級(jí)。
注意:從JDK 15開(kāi)始,偏向鎖被標(biāo)記為廢棄,未來(lái)可能移除。因?yàn)樵趯?shí)際應(yīng)用中,它的性能提升有限,且維護(hù)成本高。
2.3.4 輕量級(jí)鎖(Lightweight Locking)
適用場(chǎng)景:兩個(gè)線程交替執(zhí)行同步塊,沒(méi)有真正的競(jìng)爭(zhēng)。
原理:
- 線程在自己的棧幀中創(chuàng)建Lock Record,存儲(chǔ)對(duì)象頭的拷貝
- 通過(guò)CAS嘗試將對(duì)象頭指向Lock Record
- 如果成功,獲取輕量級(jí)鎖
- 如果失敗,說(shuō)明有競(jìng)爭(zhēng),升級(jí)為重量級(jí)鎖
輕量級(jí)鎖的解鎖:
- 通過(guò)CAS將對(duì)象頭恢復(fù)為原Mark Word
- 如果恢復(fù)成功,解鎖完成
- 如果失敗,說(shuō)明已經(jīng)升級(jí)為重量級(jí)鎖,走重量級(jí)鎖解鎖流程
2.3.5 重量級(jí)鎖(Heavyweight Locking)
適用場(chǎng)景:多個(gè)線程激烈競(jìng)爭(zhēng)。
原理:
- 線程進(jìn)入
_EntryList隊(duì)列阻塞 - 依賴操作系統(tǒng)Mutex Lock實(shí)現(xiàn)
- 涉及用戶態(tài)和內(nèi)核態(tài)切換,開(kāi)銷(xiāo)較大
2.3.6 鎖升級(jí)流程總結(jié)
偏向鎖
│
│ 有其他線程嘗試獲取
↓
輕量級(jí)鎖
│
│ 有真實(shí)競(jìng)爭(zhēng)
↓
重量級(jí)鎖2.4 synchronized與volatile的對(duì)比
| 特性 | synchronized | volatile |
|---|---|---|
| 原子性 | ? 保證 | ? 不保證 |
| 可見(jiàn)性 | ? 保證 | ? 保證 |
| 有序性 | ? 保證 | ? 保證(禁止重排序) |
| 用法 | 修飾方法或代碼塊 | 修飾變量 |
| 性能 | 較重(但有優(yōu)化) | 極輕 |
| 適用場(chǎng)景 | 復(fù)合操作 | 單一變量狀態(tài)標(biāo)志 |
volatile適用示例:
public class VolatileDemo {
private volatile boolean flag = true; // 只作為狀態(tài)標(biāo)志
public void stop() {
flag = false; // 簡(jiǎn)單寫(xiě)操作
}
public void run() {
while (flag) {
// 執(zhí)行任務(wù)
}
}
}2.5 synchronized與ReentrantLock的對(duì)比
2.5.1 對(duì)比表格
| 對(duì)比維度 | synchronized | ReentrantLock |
|---|---|---|
| 實(shí)現(xiàn)方式 | JVM關(guān)鍵字 | Java API(基于AQS) |
| 鎖釋放 | 自動(dòng)釋放 | 必須手動(dòng)unlock |
| 公平性 | 非公平 | 可設(shè)置公平/非公平 |
| 可中斷 | 不支持 | 支持lockInterruptibly() |
| 超時(shí)獲取 | 不支持 | 支持tryLock(timeout) |
| 嘗試獲取 | 不支持 | 支持tryLock() |
| 條件變量 | 一個(gè)等待集 | 多個(gè)Condition |
| 鎖狀態(tài)查詢 | 不支持 | 支持查詢持有線程等 |
2.5.2 如何選擇?
優(yōu)先使用synchronized的情況:
- 同步邏輯簡(jiǎn)單,不需要高級(jí)功能
- 希望代碼簡(jiǎn)潔不易出錯(cuò)
- JVM持續(xù)優(yōu)化,性能已很好
選擇ReentrantLock的情況:
- 需要公平鎖
- 需要嘗試獲取鎖或超時(shí)獲取
- 需要可中斷的鎖獲取
- 需要多個(gè)條件變量(如生產(chǎn)者-消費(fèi)者模式)
- 高競(jìng)爭(zhēng)場(chǎng)景需要更精細(xì)控制
2.5.3 ReentrantLock使用示例
ReentrantLock lock = new ReentrantLock(true); // 公平鎖
Condition notFull = lock.newCondition();
Condition notEmpty = lock.newCondition();
// 標(biāo)準(zhǔn)使用模式
lock.lock();
try {
// 臨界區(qū)代碼
while (條件不滿足) {
notEmpty.await(); // 等待
}
// 執(zhí)行操作
notFull.signal();
} finally {
lock.unlock(); // 必須釋放
}2.6 實(shí)戰(zhàn):線程安全的單例模式
綜合運(yùn)用synchronized,實(shí)現(xiàn)幾種經(jīng)典的單例模式。
2.6.1 餓漢式(線程安全)
public class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return INSTANCE;
}
}2.6.2 懶漢式(同步方法版)
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}2.6.3 雙重檢查鎖(DCL)
public class DCLSingleton {
// volatile保證可見(jiàn)性和禁止重排序
private static volatile DCLSingleton instance;
private DCLSingleton() {}
public static DCLSingleton getInstance() {
if (instance == null) {
synchronized (DCLSingleton.class) {
if (instance == null) {
instance = new DCLSingleton();
}
}
}
return instance;
}
}為什么需要volatile?instance = new DCLSingleton()不是原子操作,可能發(fā)生指令重排序。如果不加volatile,其他線程可能拿到一個(gè)未初始化完成的對(duì)象。這是DCL的關(guān)鍵細(xì)節(jié)。
2.7 第二課時(shí)小結(jié)
- synchronized底層基于Monitor實(shí)現(xiàn),字節(jié)碼層面使用monitorenter/monitorexit或ACC_SYNCHRONIZED
- 鎖升級(jí)機(jī)制(偏向鎖→輕量級(jí)鎖→重量級(jí)鎖)大幅提升了性能
- synchronized保證原子性、可見(jiàn)性、有序性,是全面的同步工具
- 與volatile相比,synchronized更重量但功能更全
- 與ReentrantLock相比,synchronized簡(jiǎn)單易用,ReentrantLock功能更豐富
- 實(shí)際開(kāi)發(fā)中,根據(jù)場(chǎng)景選擇合適的同步機(jī)制
課程總結(jié)
通過(guò)兩個(gè)課時(shí)的學(xué)習(xí),我們?nèi)嬲莆樟藄ynchronized關(guān)鍵字:
- 第一課時(shí):從線程安全問(wèn)題出發(fā),學(xué)習(xí)了synchronized的三種使用方式、鎖的范圍、可重入性等基礎(chǔ)概念
- 第二課時(shí):深入底層,剖析了Monitor機(jī)制、鎖升級(jí)流程,并對(duì)比了volatile和ReentrantLock
synchronized作為Java最基礎(chǔ)的同步工具,雖然簡(jiǎn)單,但背后的原理并不簡(jiǎn)單。理解它的實(shí)現(xiàn)機(jī)制,不僅能幫助我們寫(xiě)出更正確的并發(fā)程序,還能在面試中脫穎而出。
課后思考題
- 如果一個(gè)線程在同步塊中拋出異常,鎖會(huì)自動(dòng)釋放嗎?為什么?
- 偏向鎖在JDK 15中被廢棄的原因是什么?談?wù)勀愕睦斫狻?/li>
- 如何用synchronized實(shí)現(xiàn)一個(gè)阻塞隊(duì)列?
- 為什么說(shuō)synchronized是“悲觀鎖”,而CAS是“樂(lè)觀鎖”?
到此這篇關(guān)于Java synchronized關(guān)鍵字詳解:從入門(mén)到原理(兩課時(shí))的文章就介紹到這了,更多相關(guān)Java synchronized關(guān)鍵字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring boot如何通過(guò)@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及多線程配置
這篇文章主要介紹了Spring boot如何通過(guò)@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及多線程配置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
Java實(shí)現(xiàn)模擬機(jī)器人對(duì)話的示例代碼
本文主要介紹了Java實(shí)現(xiàn)模擬機(jī)器人對(duì)話的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
最新Spring Security的基于內(nèi)存用戶認(rèn)證方式
本文講解SpringSecurity內(nèi)存認(rèn)證配置,適用于開(kāi)發(fā)、測(cè)試等場(chǎng)景,通過(guò)代碼創(chuàng)建用戶及權(quán)限管理,支持密碼加密,雖簡(jiǎn)單但不持久化,生產(chǎn)環(huán)境推薦使用數(shù)據(jù)庫(kù)或JWT等認(rèn)證方式,感興趣的朋友一起看看吧2025-07-07
Java實(shí)現(xiàn)在線五子棋對(duì)戰(zhàn)游戲(人機(jī)對(duì)戰(zhàn))
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)在線五子棋對(duì)戰(zhàn)游戲(人機(jī)對(duì)戰(zhàn)),文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的可以嘗試一下2022-09-09
JDBC利用C3P0數(shù)據(jù)庫(kù)連接池連接數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了JDBC利用C3P0數(shù)據(jù)庫(kù)連接池連接數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
Java Socket+多線程實(shí)現(xiàn)多人聊天室功能
這篇文章主要為大家詳細(xì)介紹了Java Socket+多線程實(shí)現(xiàn)多人聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07

