详解 synchronized 关键字【通俗易懂】

一、前言

  • synchronized 关键字是 Java 实现线程同步的核心机制。
  • 用于解决多线程环境下的资源竞争问题,保证线程安全

二、关键作用

1.同步方法

public class Counter {
    private int count = 0;

    // 同步方法(实例方法)
    public synchronized void increment() {
        count++;
    }

    // 同步静态方法
    public static synchronized void staticMethod() {
        // 操作静态变量
    }
}
  • 实例方法:锁对象是当前实例(this),同一时刻只有一个线程能访问该实例的同步方法
  • 静态方法:锁对象是类的 Class 对象(如 Counter.class),锁住所有调用该静态方法的线程

2.同步代码块

public void doSomething() {
    // 非同步代码
    synchronized(this) { // 锁对象可以是任意对象
        // 需要同步的代码
    }
}
  • 更细粒度控制,允许仅同步关键代码段(临界区)
  • 锁对象可以是 this、Class 对象或自定义对象

三、实际应用(代码示例)

  • 假设需要对银行账户进行相关操作:
class BankAccount {
    private int balance = 1000;

    // 同步取款方法
    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            System.out.println(Thread.currentThread().getName() + " 取款:" + amount);
            balance -= amount;
        }
    }

    public int getBalance() {
        return balance;
    }
}

  public class Main {
    public static void main(String[] args) throws InterruptedException {
        BankAccount account = new BankAccount();

        // 创建两个线程同时取款
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                account.withdraw(10);
            }
        }, "线程1");

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                account.withdraw(10);
            }
        }, "线程2");

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("最终余额:" + account.getBalance()); // 正确结果应为 0
    }
}

四、关键特性

  • 可重入性:线程获得锁后可以重复获取同一把锁 。
  • 内存可见性:synchronized 会触发内存屏障,保证变量修改对后续线程可见
  • 互斥性:同一时刻只有一个线程能持有锁。

五、注意事项

  • 避免锁住非 final 对象(可能被重新赋值导致锁失效) 。
  • 不要锁字符串常量(可能与其他代码意外共享锁) 。
  • 优先使用同步代码块缩小同步范围 。
  • Java 5+推荐使用 java.util.concurrent 包中的更高级并发工具(如 ReentrantLock)。
  • 通过合理使用 synchronized,可以有效解决多线程环境下的线程安全问题。
  • 过度使用会导致性能下降,需在安全性和性能之间权衡。

你可能感兴趣的:(java,javaSE,多线程,并发编程,线程安全,同步机制,锁)