java中的synchronized关键字

发布于:2025-08-03 ⋅ 阅读:(15) ⋅ 点赞:(0)

  synchronized是 Java 中用于实现​​线程同步​​的关键字,它提供了一种​​互斥访问共享资源​​的机制,确保多个线程在访问临界区(Critical Section)时不会发生数据竞争(Data Race),从而保证线程安全。


1. synchronized的作用​

synchronized的主要作用是:

  1. ​互斥访问(Mutual Exclusion)​​:确保同一时间只有一个线程可以进入同步代码块或方法,防止多个线程同时修改共享数据。

  2. ​可见性(Visibility)​​:确保线程对共享变量的修改对其他线程立即可见(类似于 volatile的可见性保证)。

  3. ​有序性(Ordering)​​:防止指令重排序,确保同步代码块内的操作按预期顺序执行。

2. synchronized的底层原理​

  synchronized的底层实现依赖于 ​​JVM 的 Monitor(监视器)机制​​ 和 ​​Monitor Enter/Monitor Exit 指令​​。

​2.1. Monitor(监视器)机制​

  • 每个 Java 对象都有一个 ​​Monitor(监视器锁)​​,也称为 ​​内置锁(Intrinsic Lock)​​ 或 ​​对象锁​

  • 当线程进入 synchronized代码块时,会尝试 ​​获取该对象的 Monitor 锁​​(MonitorEnter

  • 如果锁已被其他线程持有,则当前线程会 ​​阻塞​​,直到锁被释放

  • 当线程退出 synchronized代码块时,会 ​​释放 Monitor 锁​​(MonitorExit

2.2. JVM 指令​

synchronized方法或代码块在字节码层面会被编译为:

  • monitorenter​(进入同步块,获取锁)

  • monitorexit​(退出同步块,释放锁)

如果发生异常,JVM 会确保 monitorexit被执行,防止死锁。​


3. synchronized的使用方式​ 

​3.1. 同步实例方法(同步当前对象) 

public class Counter {
    private int count = 0;

    // 同步实例方法,锁的是当前对象(this)
    public synchronized void increment() {
        count++;
    }
}
  • ​锁对象​​:当前实例对象(this)。

  • ​作用范围​​:整个方法体。

  • ​适用场景​​:当多个线程访问同一个对象的同步方法时,同一时间只有一个线程可以执行该方法。

3.2. 同步静态方法(同步类对象)​ 

public class Counter {
    private static int count = 0;

    // 同步静态方法,锁的是当前类的 Class 对象(Counter.class)
    public static synchronized void increment() {
        count++;
    }
}
  • ​锁对象​​:当前类的 Class对象(如 Counter.class)。

  • ​作用范围​​:整个静态方法体。

  • ​适用场景​​:当多个线程访问同一个类的静态同步方法时,同一时间只有一个线程可以执行该方法。

3.3. 同步代码块(灵活控制锁对象)​

public class Counter {
    private int count = 0;
    private final Object lock = new Object(); // 自定义锁对象

    public void increment() {
        synchronized (lock) { // 同步代码块,锁的是 lock 对象
            count++;
        }
    }
}
  • ​锁对象​​:可以是任意对象(如 thisClass对象、自定义对象)。

  • ​作用范围​​:仅限于 synchronized块内的代码。

  • ​适用场景​​:当只需要同步部分代码时,使用同步代码块可以提高性能(减少锁的粒度)。

4. volatile 与synchronized的核心功能对比

特性

synchronized

volatile

​原子性​

✅ 保证代码块或方法的原子性(复合操作)

❌ 仅保证单次读/写操作的原子性(如 i++不安全)

​可见性​

✅ 保证线程修改后对其他线程立即可见

✅ 保证线程修改后对其他线程立即可见

​有序性​

✅ 防止指令重排序(同步块内的操作顺序固定)

✅ 防止指令重排序(volatile读写前后插入内存屏障)

​阻塞机制​

✅ 线程竞争锁时会阻塞,直到获取锁

❌ 不会导致线程阻塞

​适用场景​

复杂同步(如多步操作、临界区保护)

单一变量可见性(如状态标志)

  • volatile性能更高​​:因为它不涉及锁竞争和线程阻塞,仅通过内存屏障保证可见性。

  • synchronized在低竞争时优化后性能接近 volatile​,但在高竞争时会显著变慢。