首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

Java 線程同步關鍵字 synchronized 深度解析

     編輯:J2ME

前言

synchronized 是 Java 實現多線程同步的核心關鍵字,看似簡單卻暗藏玄機。本文系統梳理其作用於不同位置時的鎖對象差異、同步方法與同步塊的等價關係,以及避免死鎖、減少開銷的最佳實踐。

核心原則

  • A:synchronized 鎖定的是對象,而非代碼塊或方法本身。
  • B:每個對象僅關聯一把鎖。
  • C:同步帶來系統開銷,甚至可能導致死鎖,應盡量避免無謂同步。

四種鎖定目標詳解

1. 實例方法(同步方法)

public synchronized void methodAAA() { ... }
// 等價於
public void methodAAA() {
    synchronized (this) { ... }
}

鎖對象為調用該方法的實例對象(如 P1)。同一實例的多線程調用會互斥,但不同實例(P2)互不干擾,可能導致數據競態。

2. 同步塊——指定對象引用

public void method3(SomeObject so) {
    synchronized (so) { ... }
}

鎖為參數 so 指向的對象。若需同步一段無明確對象的代碼,可創建專用鎖對象:

private byte[] lock = new byte[0]; // 零長度 byte[] 開銷最小(3 條字節碼 vs Object 7 條)
synchronized (lock) { ... }

3. 靜態方法

public synchronized static void methodAAA() { ... }
// 等價於
public void methodBBB() {
    synchronized (Foo.class) { ... }
}

鎖為類對象(Class Literal),即 Foo.class。注意 P1.getClass() 若為子類則不可用作同類鎖。

4. 類字面常量

直接使用 synchronized (Foo.class),效果同靜態同步方法,鎖定當前類的 Class 對象。

關鍵推論

同一類中,synchronized static 方法與 synchronized instance 方法鎖不同(Class vs 實例),兩者並發執行不會互斥,若共享靜態/實例變量需額外協調。

安全共享資源的技巧

  1. 封裝變量:定義 private 實例變量 + getter,避免 public/protected 變量繞過同步控制。
  2. 防御性拷貝:若變量為可變對象(數組、ArrayList),getter 應同步並返回 clone() 副本,防止外部修改內部狀態。

總結

搞清「鎖是誰」是編寫正確多線程程序的前提。合理選擇同步粒度、縮小同步塊範圍、優先使用 java.util.concurrent 高級工具,才能在保證線程安全的同時兼顧性能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved