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

Java 多線程同步區塊詳解與實例

     編輯:Java 相關知識

前言

synchronized 關鍵字是 Java 實現線程同步的核心機制。同步區塊可鎖定任意物件,粒度比同步方法更細,能有效減少競爭範圍。本文系統說明四種同步形式、監視器物件原理與實戰範例。

一、四種同步形式

形式鎖定物件適用場景
實例方法同步this(當前實例)保護實例級共享資源
靜態方法同步類別物件(ClassName.class)保護類別級共享資源
實例方法中的同步區塊指定物件(常用 this 或私有鎖)僅同步方法部分程式碼
靜態方法中的同步區塊指定物件(常用 ClassName.class)僅同步靜態方法部分程式碼

二、代碼示範

1. 實例方法同步 vs 同步區塊(等效)

public class MyClass {
    // 同步方法
    public synchronized void log1(String msg1, String msg2) {
        log.writeln(msg1); log.writeln(msg2);
    }
    // 同步區塊,鎖定 this
    public void log2(String msg1, String msg2) {
        synchronized(this) {
            log.writeln(msg1); log.writeln(msg2);
        }
    }
}

兩者同步於同一實例,效果等同。

2. 靜態方法同步 vs 同步區塊(等效)

public class MyClass {
    public static synchronized void log1(String msg1, String msg2) { ... }
    public static void log2(String msg1, String msg2) {
        synchronized(MyClass.class) { ... }
    }
}

3. 不同鎖物件可並行執行

public class Counter {
    long count = 0;
    public synchronized void add(long value) { this.count += value; }
}

// 兩線程共用同一 Counter 實例 -> 串行執行
Counter counter = new Counter();
new Thread(() -> counter.add(1)).start();
new Thread(() -> counter.add(1)).start();

// 兩線程各用不同 Counter 實例 -> 並行執行
Counter counterA = new Counter(), counterB = new Counter();
new Thread(() -> counterA.add(1)).start();
new Thread(() -> counterB.add(1)).start();

三、完整生產者-消費者範例

class Goods {
    private String name; private int num; private boolean flag = false;
    public synchronized void produce(String name) {
        while (flag) { try { wait(); } catch (InterruptedException e) {} }
        this.name = name + "編號:" + num++;
        System.out.println(Thread.currentThread().getName() + "生產:" + this.name);
        flag = true; notifyAll();
    }
    public synchronized void consume() {
        while (!flag) { try { wait(); } catch (InterruptedException e) {} }
        System.out.println(Thread.currentThread().getName() + "消費:" + name);
        flag = false; notifyAll();
    }
}

四、關鍵重點

  • 同步區塊必須指定監視器物件(synchronized(obj)),僅有一線程能進入同一監視器的同步區塊。
  • 選擇恰當鎖物件:實例資源用 this 或私有 final Object lock = new Object();類別資源用 ClassName.class。
  • wait()/notify()/notifyAll() 必須在同步區塊內呼叫,且作用於同一監視器物件。
  • 使用 while 而非 if 檢查條件,防止虛假喚醒。

五、總結

同步區塊提供比同步方法更細粒度的鎖控制,能顯著提升並發效能。掌握監視器物件選擇、條件等待與喚醒機制,是編寫正確高效多線程程式的基礎。

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