当前位置:首页 > Java > 正文

深入理解Java锁机制(从synchronized到ReentrantLock的全面教程)

在多线程编程中,Java锁机制是确保线程安全的核心手段。对于初学者来说,理解锁的概念和使用方法是掌握Java并发编程的关键一步。本教程将用通俗易懂的语言,带你从最基础的 synchronized 关键字讲起,逐步过渡到更灵活的 ReentrantLock,让你彻底搞懂 Java 中的锁是如何工作的。

为什么需要锁?

想象一下:多个线程同时修改同一个变量,比如银行账户余额。如果没有锁,可能会出现“脏读”或“数据不一致”的问题。锁的作用就是让同一时间只有一个线程能访问共享资源,从而保证数据安全。

深入理解Java锁机制(从synchronized到ReentrantLock的全面教程) Java锁机制 Java并发编程 Java synchronized ReentrantLock 第1张

1. 使用 synchronized 关键字

synchronized 是 Java 最基础的锁机制,它有两种用法:修饰方法或修饰代码块。

1.1 同步方法

public class BankAccount {    private int balance = 1000;    public synchronized void withdraw(int amount) {        if (balance >= amount) {            balance -= amount;            System.out.println(Thread.currentThread().getName() +                                " 提款成功,余额:" + balance);        } else {            System.out.println("余额不足");        }    }}

在这个例子中,withdraw 方法被 synchronized 修饰,意味着同一时间只能有一个线程执行该方法。

1.2 同步代码块

有时我们不需要锁住整个方法,只需锁住关键代码段:

public void transfer(BankAccount from, BankAccount to, int amount) {    synchronized (from) {        synchronized (to) {            if (from.getBalance() >= amount) {                from.withdraw(amount);                to.deposit(amount);            }        }    }}

这里使用了两个嵌套的 synchronized 块,分别锁定两个账户对象,避免死锁风险(实际开发中需谨慎处理锁顺序)。

2. 使用 ReentrantLock(可重入锁)

从 Java 5 开始,java.util.concurrent.locks.ReentrantLock 提供了比 synchronized 更灵活的锁控制。它是 Java ReentrantLock 的典型代表,支持公平锁、可中断、超时等待等高级特性。

import java.util.concurrent.locks.ReentrantLock;public class SafeCounter {    private int count = 0;    private final ReentrantLock lock = new ReentrantLock();    public void increment() {        lock.lock(); // 获取锁        try {            count++;        } finally {            lock.unlock(); // 必须在 finally 中释放锁        }    }    public int getCount() {        lock.lock();        try {            return count;        } finally {            lock.unlock();        }    }}

注意:使用 ReentrantLock 时,必须在 finally 块中调用 unlock(),否则可能导致死锁。

3. synchronized vs ReentrantLock 对比

  • synchronized:JVM 内置,自动加锁/释放,简单但功能有限。
  • ReentrantLock:API 级别,手动控制,支持更多功能(如 tryLock、lockInterruptibly)。
  • 性能方面:Java 6 之后,synchronized 经过优化,与 ReentrantLock 性能接近。
  • 建议:简单场景用 synchronized;复杂需求(如超时、公平锁)用 ReentrantLock

总结

掌握 Java锁机制 是编写安全、高效并发程序的基础。无论是使用传统的 synchronized 还是更现代的 ReentrantLock,核心思想都是“互斥访问”。希望本教程能帮助你轻松入门 Java并发编程,并在实际项目中正确使用锁来避免线程安全问题。

提示:实际开发中,尽量减少锁的粒度,避免长时间持有锁,以提升程序并发性能。