← 每日面试题 学习看板

synchronized是如何保证原子性、可见性、有序性的?

面试题/00java/02Java 并发编程/06线程同步与锁机制/synchronized是如何保证原子性、可见性、有序性的?.md

面试记录 2026-09-26

题目:synchronized 是如何保证原子性、可见性、有序性的?

难度:high

标签:java/lock, general/knowledge

评分:⭐⭐☆☆☆

我的回答

Xenon 是通过锁去保证这一整个的线程并发的处理的。通过锁来保证原子性,内核级的锁,它在指令中添加了锁的指令,去确保锁内只有同一个线程在执行。可见性方面,由于它通过锁控制,其他线程是不会进入的,其他线程会被阻塞,放到阻塞队列中,并不存在可见性问题,当前线程可见当前内容。有序性方面,它也是通过它是通过公平锁来实现的,顺序的去处理锁的线程。如果是这个有序性指的是指令重排,那么它也是通过锁的指令,在内核程序去保证锁指令重排的不发生。

点评

优点:抓到核心方向——synchronized 通过"锁"机制保证原子性;大致意识到可见性来自其他线程进不来

不足:严重错误——synchronized 不是公平锁而是非公平锁;有序性理解错误(混淆了指令重排与线程获取顺序);未说三大特性的底层机制(Monitor 互斥、解锁刷内存、内存屏障);未提 happens-before 规则

补充:原子性=Monitor 互斥、可见性=解锁刷内存+加锁 reload、有序性=JIT 禁止重排;synchronized 是非公平锁;volatile 只保证可见+有序,synchronized 三个都保证

完整讲解

第一部分:知识重点剖析

核心考点定位:能否说清"原子性 = 互斥"、"可见性 = 解锁刷内存"、"有序性 = 禁止指令重排"这三条底层机制,以及 happens-before 规则。

知识点拆解:

  1. 原子性 ← Monitor 互斥机制:
  1. 可见性 ← 解锁刷内存 + 内存屏障:
  1. 有序性 ← 禁止指令重排:
  1. happens-before 规则(JMM 第 17 条):
  1. 三大特性对比 volatile:
按「底层原理 → 设计权衡 → 工程实践」递进排列。

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. synchronized 能保证原子性,为什么不用 volatile 也能保证可见性和有序性?
  1. synchronized 是公平锁吗?为什么说是非公平锁?
  1. happens-before 有哪些传递性规则?

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,synchronized 同时保证三个特性:原子性、可见性、有序性,但每一条的底层机制是不同的,我分开说。

先说原子性。原子性的本质是"互斥"——同一时刻只能有一个线程在 synchronized 块里执行。它的底层是 Monitor(管程)机制。每个对象都隐含一个 Monitor 对象,里面有个 owner 指针记录当前的持锁线程。线程进入 synchronized 块时,先尝试用 CAS 把 owner 设成自己;成功了就独占执行,失败了就在队列里等。重量级锁状态下其他线程会挂起到 entryList 阻塞等待,轻量级锁下通过自旋 CAS 竞争。所以从"互斥"这个角度看,原子性其实是锁的基本性质——你进得去,别人就进不来,操作就整体执行。

再说可见性。可见性靠的是解锁和加锁时强制刷内存。具体规则是:

这样"解锁 → 加锁"之间的修改对其他线程一定可见。JMM 把它总结成一条规则:对一个 synchronized 块的解锁,happens-before 后续对同一把锁的加锁。这是 JMM 第 17 条规则,是并发编程可见性的契约基础。

第三个是有序性。这里的有序性不是指"线程获取锁的顺序",而是指令重排——JIT 编译器不会把 synchronized 块内部的指令重排到块外部去。CPU 层面的 StoreLoad 屏障也保证了跨块的指令顺序不会被破坏。这个很重要,比如经典的 DCL 单例如果不加 volatile,new 指令会被重排成"分配内存→赋引用→初始化构造器",不加锁的话其他线程可能看到半构造实例。synchronized 块里因为有序性保证,指令不会被这样重排。

对比一下 volatile:volatile 只保证可见性和有序性,但不保证原子性——i++ 是读-改-写三步,volatile 只能让每步都可见,但三步之间可能交错。synchronized 通过互斥机制把三步包成一个整体,所以三个特性都保证。所以可以说 synchronized 是 volatile 的"超集",但开销也更大。

关于公平性——这里要纠正一个常见误解:synchronized 不是公平锁,它是非公平锁。JVM 内部不保证先到先得,多个线程竞争时随机调度。如果需要公平性,必须用 ReentrantLock(true)。

这就是我对 synchronized 三大特性的理解。


面试记录 2026-10-17(第 2 次)

题目:synchronized 是如何保证原子性、可见性、有序性的?

难度:high

标签:java/lock, general/knowledge

评分:⭐⭐⭐⭐☆(4/5)

练习次数:2

我的回答

synchronized在不同锁等级下使用不同的方式来实现原子,可见,有序的,以重量锁来说 通过cpu提供的lock指令来实现多线程的互斥,实现一个线程在临界区域进行原子操作的; 通过释放锁后,通知主存,唤醒其他阻塞线程,来实现多线程的可见性的; 通过happend-before语义,内存屏障来实现阻止指令重排实现有序性的

点评

优点:三条机制映射正确——原子性 = lock 指令互斥、可见性 = 释放刷主存、有序性 = 屏障禁重排。比首次(2026-09-26,2/5,且当时把 synchronized 误说成公平锁)大幅进步。

不足:缺 Monitor/entryList 机制、加锁时 reload、"unlock happens-before lock" 规则;"通知主存唤醒其他线程"表述偏松——唤醒靠 monitor,可见靠刷主存,是两件事。

补充:synchronized 是非公平锁;volatile 只保可见+有序,synchronized 三者都保。

ℹ️ 完整讲解见上方首次记录(2026-09-26)