醋醋百科网

Good Luck To You!

说说synchronize的用法及原理(synchronize作用)

一句话总结

synchronized用于控制多线程对共享资源的访问,可修饰方法或代码块,通过指定锁对象实现互斥。其原理基于对象内部的监视器锁(Monitor),线程进入时获取锁,退出时释放锁,底层依赖操作系统的互斥锁及内存屏障机制保证原子性与可见性。JVM会优化锁状态(偏向锁、轻量级锁等)提升性能。

详细解析

synchronized 是 Java 中用于实现线程同步的关键字,通过内置锁(Monitor)机制保证多线程环境下代码块或方法的互斥访问。以下是其用法及底层原理的详细说明:


一、synchronized 的用法

1. 修饰实例方法

  • 锁对象:当前实例对象(this)。
  • 作用范围:整个方法体。
  • 示例
public synchronized void instanceMethod() {
    // 同步代码
}

2. 修饰静态方法

  • 锁对象:类的Class对象(如MyClass.class)。
  • 作用范围:整个静态方法体。
  • 示例
public static synchronized void staticMethod() {
    // 同步代码
}

3. 修饰代码块

  • 锁对象:显式指定的任意对象(通常为共享资源)。
  • 作用范围:代码块内部。
  • 示例
private final Object lock = new Object();

public void blockMethod() {
    synchronized (lock) {
        // 同步代码
    }
}

二、synchronized 的原理

1. 底层实现

  • 字节码指令:通过monitorenter和monitorexit指令实现锁的获取与释放。
  • 对象头结构:每个 Java 对象在内存中分为三部分:
    • 对象头(Header):存储锁状态、GC 分代年龄、哈希码等。
    • 实例数据(Instance Data):对象的字段值。
    • 对齐填充(Padding):补齐内存对齐。
  • 对象头中的锁标记
    • Mark Word(32/64 位):存储锁标志位(如无锁、偏向锁、轻量级锁、重量级锁)。

2. 锁升级过程

JDK 1.6 后,synchronized 引入了 锁膨胀 机制,根据竞争情况动态升级锁状态,以平衡性能与开销:

锁状态

适用场景

实现方式

无锁

无竞争

直接访问资源

偏向锁

单线程重复访问

在 Mark Word 中记录线程 ID

轻量级锁

多线程交替执行,无实际竞争

CAS 自旋获取锁

重量级锁

多线程高竞争

通过操作系统互斥量(Mutex)实现

锁升级流程

无锁 → 偏向锁 → 轻量级锁 → 重量级锁

3. 锁膨胀机制详解

  • 偏向锁
    • 目的:减少无竞争时的锁开销。
    • 触发条件:锁对象首次被线程访问。
    • 实现:Mark Word 记录线程 ID,后续无需 CAS 操作。
    • 撤销:当其他线程尝试获取锁时,偏向锁升级为轻量级锁。
  • 轻量级锁
    • 目的:减少线程阻塞开销,通过自旋(CAS)竞争锁。
    • 触发条件:多个线程交替执行,未发生竞争。
    • 实现:将对象头替换为指向线程栈中锁记录的指针。
    • 失败处理:自旋超过阈值(默认 10 次)后升级为重量级锁。
  • 重量级锁
    • 目的:应对高并发竞争场景。
    • 实现:通过操作系统互斥量(Mutex)阻塞线程,进入等待队列。
    • 开销:涉及用户态与内核态切换,性能较低。

三、synchronized 的特性

特性

说明

互斥性

同一时间仅允许一个线程持有锁。

可见性

锁释放前,变量的修改会刷新到主内存;锁获取时,本地缓存失效。

可重入性

同一线程可重复获取同一把锁(锁计数器递增)。

非公平锁

默认非公平,允许插队竞争,提高吞吐量。

四、示例解析

1. 单例模式(双重检查锁)

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • volatile 作用:防止指令重排序导致未初始化对象被引用。
  • synchronized 作用:保证单例创建的原子性。
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言