• 作者:老汪软件技巧
  • 发表时间:2024-09-26 00:01
  • 浏览量:

Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。

来自微信小程序「猿面试」每日分享一道大厂面试题,涉及 Java、Android、鸿蒙和ArkTS、设计模式、算法和数据结构 等内容。

volatile 和 synchronized 的区别

在 Java 中,volatile 和 synchronized 都是用于控制多线程环境下的并发访问,但它们的作用和使用场景有所不同。

可见性

volatile 关键字确保变量的修改对所有线程是可见的。当一个线程修改了 volatile 变量的值,这个修改会立即被写入主内存,并且其他线程在读取该变量时会从主内存中获取最新的值。然而,volatile 只保证变量本身的可见性,不保证整个代码块的可见性。这是通过禁止指令重排序和强制将缓存中的数据写回主内存来实现的。

synchronized 关键字不仅保证变量的可见性,还保证整个代码块的可见性。当一个线程进入 synchronized 代码块时,它会从主内存中读取所有变量的最新值,并且在退出 synchronized 代码块时,所有修改过的变量都会被刷新到主内存中。

作用范围:

volatile 只能用于修饰变量,不能用于修饰方法或代码块。

synchronized 可以用于变量、方法或代码块。

原子性

volatile 不能保证操作的原子性,也就是说,它不能保证复合操作的原子性。例如,volatile int count = 0;,如果多个线程同时执行 count++,仍然可能会出现竞态条件,因为 count++ 实际上是读-修改-写三个步骤的组合。

synchronized 可以保证操作的原子性。当一个线程进入 synchronized 代码块时,其他线程无法同时进入该代码块,从而保证了操作的原子性。

程序编程员__程序编程员工资多少

阻塞性:

volatile 不会造成线程阻塞,因为它不涉及锁机制。

synchronized 可能会造成线程阻塞,因为它涉及到锁的获取和释放,当一个线程持有锁时,其他线程必须等待

性能:

volatile 的性能优于 synchronized,因为它不需要加锁和释放锁,只是简单地通知 JVM 从主内存中读取或写入变量。

synchronized 的性能相对较低,因为它涉及到锁的获取和释放,可能会导致线程阻塞和上下文切换

应用场景:

volatile 适用于只需要保证变量可见性的场景,例如标志位的更新。

synchronized 适用于需要保证操作原子性和代码块可见性的场景,例如多个线程对共享资源的访问。

总结

volatile 更轻量级,主要用于确保变量的可见性和防止指令重排序,但不适用于需要原子性的复合操作。

synchronized 则更为强大和通用,既能确保可见性也能确保原子性,但可能会带来更大的性能开销。在某些情况下,也可以将 volatile 和 synchronized 结合起来使用,以实现更精细的线程控制,比如常用单例模式。

更多大厂面试题,欢迎前往微信搜索小程序 「猿面试」 查看。微信小程序 (猿面试) 包含了 Java、Android、鸿蒙和ArkTS、设计模式、算法和数据结构 相关内容,