Java Synchronized 全局锁:理解与实践

在 Java 编程中,多线程编程是一个经常遇到的主题,而 synchronized 关键字是用于处理线程安全问题的一个重要工具。本文将详细探讨“全局锁”概念,并通过代码示例来加深理解。

什么是全局锁?

全局锁是指在整个应用程序范围内只有一个线程能够访问某一资源。这通常是通过 synchronized 关键字实现的。全局锁确保在同一时刻,只有一个线程可以执行特定的方法或代码块,从而避免数据不一致或竞争条件的发生。

Synchronized 的使用

synchronized 可以用于方法和代码块。其基本语法如下:

public synchronized void synchronizedMethod() {
    // 需要线程安全的代码逻辑
}

或者使用代码块:

public void methodWithBlock() {
    synchronized (this) {
        // 需要线程安全的代码逻辑
    }
}

其中,this 表示当前对象的监视器锁。

全局锁与局部锁的对比

使用全局锁的方式会限制其他线程的并行执行,可能导致性能下降。以下是全局锁和局部锁的对比:

特性 全局锁 局部锁
锁范围 整个类/对象 代码块
性能影响 性能下降,线程饥饿 影响较小,改善并行执行
锁控制 简单,但不灵活 更灵活,锁和队列可控

示例代码

以下代码展示了全局锁的使用。我们将定义一个简单的银行账户类,处理存款和取款操作:

public class BankAccount {
    private int balance = 0;

    // 全局锁:synchronized 方法
    public synchronized void deposit(int amount) {
        balance += amount;
    }

    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount;
        }
    }

    public int getBalance() {
        return balance;
    }
}

在上述代码中,depositwithdraw 方法使用了全局锁,以确保在任何给定时刻只允许一个线程修改账户余额。

线程操作示例

以下是一个线程操作的示例,展示了如何调用这些方法:

public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount();
        
        // 创建存款线程
        Thread depositThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                account.deposit(100);
                System.out.println("Deposited: 100, Current Balance: " + account.getBalance());
            }
        });

        // 创建取款线程
        Thread withdrawThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                account.withdraw(50);
                System.out.println("Withdrew: 50, Current Balance: " + account.getBalance());
            }
        });

        depositThread.start();
        withdrawThread.start();
    }
}

类图

下面是 BankAccount 类的类图:

classDiagram
class BankAccount {
    -int balance
    +void deposit(int amount)
    +void withdraw(int amount)
    +int getBalance()
}

结尾

全局锁在 Java 中是一种有效的同步机制,能够解决线程安全问题。然而,它也会导致线程的阻塞,从而影响程序的性能。在设计时,需要权衡全局锁的使用与局部锁的效率。理解这一点对于开发高效且线程安全的 Java 应用程序至关重要。希望通过本篇文章与代码示例,能使你更好地理解 Java 中的全局锁。