volatile和synchronized的区别

简介: volatile和synchronized特点首先需要理解线程安全的两个方面:执行控制和内存可见。执行控制的目的是控制代码执行(顺序)及是否可以并发执行。内存可见控制的是线程执行结果在内存中对其它线程的可见性。根据Java内存模型的实现,线程在具体执行时,会先拷贝主存数据到线程本地(CPU缓存),操作完成后再把结果从线程本地刷到主存。synchronized关

volatile和synchronized特点

首先需要理解线程安全的两个方面:执行控制内存可见

执行控制的目的是控制代码执行(顺序)及是否可以并发执行。

内存可见控制的是线程执行结果在内存中对其它线程的可见性。根据Java内存模型的实现,线程在具体执行时,会先拷贝主存数据到线程本地(CPU缓存),操作完成后再把结果从线程本地刷到主存。

synchronized关键字解决的是执行控制的问题,它会阻止其它线程获取当前对象的监控锁,这样就使得当前对象中被synchronized关键字保护的代码块无法被其它线程访问,也就无法并发执行。更重要的是,synchronized还会创建一个内存屏障,内存屏障指令保证了所有CPU操作结果都会直接刷到主存中,从而保证了操作的内存可见性,同时也使得先获得这个锁的线程的所有操作,都happens-before于随后获得这个锁的线程的操作。

volatile关键字解决的是内存可见性的问题,会使得所有对volatile变量的读写都会直接刷到主存,即保证了变量的可见性。这样就能满足一些对变量可见性有要求而对读取顺序没有要求的需求。

使用volatile关键字仅能实现对原始变量(如boolen、 short 、int 、long等)操作的原子性,但需要特别注意, volatile不能保证复合操作的原子性,即使只是i++,实际上也是由多个原子操作组成:read i; inc; write i,假如多个线程同时执行i++volatile只能保证他们操作的i是同一块内存,但依然可能出现写入脏数据的情况。

在Java 5提供了原子数据类型atomic wrapper classes,对它们的increase之类的操作都是原子操作,不需要使用sychronized关键字。

对于volatile关键字,当且仅当满足以下所有条件时可使用:

1. 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
2. 该变量没有包含在具有其他变量的不变式中。

volatile和synchronized的区别

  1. volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  2. volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
  3. volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
  4. volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
  5. volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

如果想更好地理解这两个关键字的作用,强烈建议看一下这篇文章:Java内存模型

目录
相关文章
|
安全 Java 编译器
kotlin面试题
kotlin面试题
782 1
|
5月前
|
SQL 监控 数据可视化
如何选择好用的BI平台?BI报表管理与BI可视化平台功能优势比拼!
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
|
8月前
|
人工智能
RAG - 拒识模块
在RAG(Retrieval-Augmented Generation)模型中,拒识模块(或称为拒绝模块,Reject Module)是一个重要的组成部分,旨在提高生成模型在面对不相关查询或信息时的鲁棒性。RAG模型结合了检索和生成两种能力,通过在生成过程中引入外部文档来增强生成的质量和准确性。
449 2
|
存储 监控 数据库
什么是聚集索引和非聚集索引?
【8月更文挑战第3天】
7154 6
|
存储 安全 Java
synchronized原理详解(通俗易懂超级好)
当系统检查到锁是重量级锁之后,会把等待想要获得锁的线程进行阻塞,被阻塞的线程不会消耗cpu。但是阻塞或者唤醒一个线程时,都需要操作系统来帮忙,这就需要从用户态转换到内核态,而转换状态是需要消耗很多时间的,有可能比用户执行代码的时间还要长。
synchronized原理详解(通俗易懂超级好)
|
JSON 安全 调度
Android面试题之Kotlin协程一文搞定
本文介绍了协程的基础知识,强调它是轻量级线程,用于处理耗时任务而不阻塞主线程,确保主线程安全。协程特点包括使异步逻辑同步化,并允许函数挂起和恢复。挂起函数由`suspend`关键字标识,只能在协程内部调用。挂起与阻塞的主要区别在于挂起不会导致主线程ANR。 结构化并发和协程作用域(如`CoroutineScope`、`GlobalScope`、`MainScope`等)提供了任务管理,文章还探讨了并发、启动模式、协程取消、超时任务以及资源释放等主题。
191 0
|
缓存 网络协议 开发者
HTTP1.0、HTTP1.1 、HTTP2.0和HTTP3.0 的区别【面试题】
HTTP1.0、HTTP1.1 、HTTP2.0和HTTP3.0 的区别【面试题】
1667 0
HTTP1.0、HTTP1.1 、HTTP2.0和HTTP3.0 的区别【面试题】
|
监控 Java 程序员
Java中的垃圾回收机制:原理与优化实践
在Java编程语言中,垃圾回收(Garbage Collection, GC)是内存管理的关键组成部分。本文章深入探讨了Java垃圾回收的工作原理、常见的垃圾回收器类型及其特点,以及如何监控和优化垃圾回收性能。通过引用最新的研究成果和官方文档,本文旨在为Java开发者提供一套系统的垃圾回收知识体系,帮助他们更好地理解和掌握这一核心技术。
|
消息中间件 Java 中间件
RocketMQ延迟消息的代码实战及原理分析
在RocketMQ中,支持延迟消息,但是不支持任意时间精度的延迟消息,只支持特定级别的延迟消息。如果要支持任意时间精度,不能避免在Broker层面做消息排序,再涉及到持久化的考量,那么消息排序就不可避免产生巨大的性能开销。
3624 0

热门文章

最新文章