全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-10 9 分钟 ✍️ juanwangdev

程同步与锁

多线程访问共享资源需要同步机制保证线程安全,synchronized 是最基础的方式。

程安全问题

Java
// 不安全的计数器
public class UnsafeCounter {
    private int count = 0;

    public void increment() {
        count++;  // 读-改-写三步,非原子
    }

    public int getCount() {
        return count;
    }
}

// 多线程并发调用 increment(),结果不准确

count++ 不是原子操作:读取 count、加 1、写入 count,多线程交错执行导致数据丢失。

synchronized 解决线程安全

同步方法

Java
public class SafeCounter {
    private int count = 0;

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

    // 同步静态方法:锁 Class 对象
    public static synchronized void staticMethod() {
        // 同步代码
    }
}

同步代码块

Java
public class SafeCounter {
    private int count = 0;
    private final Object lock = new Object();  // 专用锁对象

    public void increment() {
        synchronized (lock) {  // 锁指定对象
            count++;
        }
    }

    public void method() {
        synchronized (this) {  // 锁当前对象
            // 同步代码
        }

        synchronized (SafeCounter.class) {  // 锁 Class 对象
            // 同步代码
        }
    }
}

推荐专用锁对象:private final Object lock = new Object(),避免外部干扰。

synchronized 锁对象

用法锁对象适用场景
synchronized 方法this实例级同步
synchronized 静态方法Class 对象类级同步
synchronized(this)当前实例代码块同步
synchronized(obj)指定对象精细控制
synchronized(Class.class)Class 对象类级同步

锁升级机制

JVM 对 synchronized 优化,锁根据竞争情况升级:

Java
无锁 → 偏向锁 → 轕量级锁 → 重量级锁
锁状态条件特点
偏向锁单线程重复获取无同步开销,最快
蕃量级锁多线程交替执行CAS 自旋,有少量开销
重量级锁竞争激烈OS 互斥量,开销最大

锁升级不可逆:升级后不会降级,竞争激烈时锁一直为重量级。

synchronized 注意事项

1. 避免锁可变对象

Java
// 错误:锁对象可能被修改
private Object lock = new Object();
lock = new Object();  // 锁变了,失效

// 正确:final 确保锁不变
private final Object lock = new Object();

2. 避免嵌套锁

Java
// 错误:可能死锁
synchronized (lockA) {
    synchronized (lockB) {
        // 代码
    }
}

3. 尽量减小锁范围

Java
// 不推荐:锁住整个方法
public synchronized void process() {
    // 大量非同步代码
    synchronized (this) {
        count++;  // 只有这行需要同步
    }
}

// 推荐:只锁必要部分
public void process() {
    // 大量非同步代码(更快)
    synchronized (this) {
        count++;
    }
}

4. 避免锁住方法参数

text
// 错误:外部对象可能被其他代码锁住
public void method(Object param) {
    synchronized (param) {
        // 可能与其他代码冲突
    }
}

synchronized vs ReentrantLock

特性synchronizedReentrantLock
获取释放自动手动 unlock
公平锁❌ 非公平✅ 可选公平
可中断✅ lockInterruptibly
超时获取✅ tryLock(timeout)
条件变量单个多个 Condition
性能JDK 6 后差距小略有优势

选择原则:优先使用 synchronized,需要公平锁、可中断、超时等高级功能时用 ReentrantLock。

要点总结

  • synchronized 保证线程安全,自动获取释放锁
  • 同步方法锁 this(实例)或 Class(静态)
  • 同步代码块可指定任意对象作为锁
  • 推荐 private final Object 作为专用锁
  • 锁升级:偏向锁 → 蕃量级锁 → 重量级锁
  • 避免锁可变对象、嵌套锁、大范围锁
  • JDK 6 后 synchronized 性能已优化,与 ReentrantLock 差距小

📝 发现内容有误?点击此处直接编辑

← 上一篇 并发工具类
下一篇 → 程池
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库