volatile和synchronized的作用及区别

本文深入解析Java线程抽象内存模型,探讨线程间通信机制,以及volatile和synchronized关键字如何确保多线程环境下的数据一致性,包括原子性、可见性和有序性的实现。

java的线程抽象内存模型

java的线程抽象内存模型中定义了每个线程都有一份自己的私有内存,里面存放自己私有的数据,其他线程不能直接访问,而一些共享数据则存在主内存中,供所有线程进行访问。 
上图中,如果线程A和线程B要进行通信,就要经过主内存,比如线程B要获取线程A修改后的共享变量的值,要经过下面两步: 
     (1)、线程A修改自己的共享变量副本,并刷新到了主内存中。 
     (2)、线程B读取主内存中被A更新过的共享变量的值,同步到自己的共享变量副本中。

java多线程中的原子性、可见性、有序性
     (1)、原子性:是指线程的多个操作是一个整体,不能被分割,要么就不执行,要么就全部执行完,中间不能被打断。 
     (2)、可见性:是指线程之间的可见性,就是一个线程修改后的结果,其他的线程能够立马知道。 
     (3)、有序性:为了提高执行效率,java中的编译器和处理器可以对指令进行重新排序,重新排序会影响多线程并发的正确性,有序性就是要保证不进行重新排序(保证线程操作的执行顺序)。

volatile关键字的作用
其实volatile关键字的作用就是保证了可见性和有序性(不保证原子性),如果一个共享变量被volatile关键字修饰,那么如果一个线程修改了这个共享变量后,其他线程是立马可知的。为什么是这样的呢?比如,线程A修改了自己的共享变量副本,这时如果该共享变量没有被volatile修饰,那么本次修改不一定会马上将修改结果刷新到主存中,如果此时B去主存中读取共享变量的值,那么这个值就是没有被A修改之前的值。如果该共享变量被volatile修饰了,那么本次修改结果会强制立刻刷新到主存中,如果此时B去主存中读取共享变量的值,那么这个值就是被A修改之后的值了。 
volatile能禁止指令重新排序,在指令重排序优化时,在volatile变量之前的指令不能在volatile之后执行,在volatile之后的指令也不能在volatile之前执行,所以它保证了有序性。

synchronized关键字的作用
synchronized提供了同步锁的概念,被synchronized修饰的代码段可以防止被多个线程同时执行,必须一个线程把synchronized修饰的代码段都执行完毕了,其他的线程才能开始执行这段代码。 
因为synchronized保证了在同一时刻,只能有一个线程执行同步代码块,所以执行同步代码块的时候相当于是单线程操作了,那么线程的可见性、原子性、有序性(线程之间的执行顺序)它都能保证了。

volatile关键字和synchronized关键字的区别
     (1)、volatile只能作用于变量,使用范围较小。synchronized可以用在变量、方法、类、同步代码块等,使用范围比较广。 
     (2)、volatile只能保证可见性和有序性,不能保证原子性。而可见性、有序性、原子性synchronized都可以包证。 
     (3)、volatile不会造成线程阻塞。synchronized可能会造成线程阻塞。

 


--------------------- 
作者:孤客无依 
来源:优快云 
原文:https://blog.youkuaiyun.com/huideveloper/article/details/80632111 
版权声明:本文为博主原创文章,转载请附上博文链接!

<think>好的,用户想了解Java中volatilesynchronized区别,包括它们的用法适用场景。首先,我需要回顾一下这两个关键字的基本概念。 根据引用[1],volatilesynchronized都用于多线程编程,但机制不同。volatile主要解决变量可见性问题,确保一个线程的修改对其他线程立即可见。而synchronized则提供互斥访问,确保代码块或方法在同一时间只有一个线程执行,同时保证可见性原子性。 接下来,引用[3]提到,volatile只能修饰变量,而synchronized可以修饰方法代码块。volatile不保证原子性,比如i++这样的操作,即使变量是volatile的,也需要synchronized来保证整个操作的原子性。而synchronized通过锁机制,既保证了可见性,也确保了原子性。 然后,引用[2]中的代码示例展示了synchronized的可重入性,一个线程在持有锁的情况下可以调用同一对象的其他synchronized方法。这说明synchronized在复杂同步场景中的灵活性,而volatile无法实现这样的功能。 引用[4]对比了volatilestatic的区别,但这里更相关的点是volatile的可见性与synchronized的同步性。性能方面,volatile是轻量级的,性能开销较小,而synchronized在JDK优化后性能有所提升,但仍有较高开销,尤其是在竞争激烈的情况下。 现在需要整理这些信息,明确两者的区别,包括作用范围、保证的特性、性能差异使用场景。要确保回答结构清晰,分点说明,并给出实际例子帮助用户理解。 用户可能的问题包括:什么时候该用volatile而不是synchronized?如何选择这两个关键字?或者它们的底层实现原理是什么?需要准备好相关问题,引导用户进一步学习。 最后,检查引用是否正确,确保每个引用标识对应正确的来源,避免混淆。同时,按照用户要求,使用中文回答,数学公式用$...$格式,但这里可能用不上。保持语言简洁明了,避免技术术语过多,必要时用例子说明。</think>### Java中volatilesynchronized区别解析 #### 一、核心区别对比 | **特性** | **volatile** | **synchronized** | |----------------------|-------------------------------------------|-------------------------------------------| | **作用范围** | 仅修饰变量(如:`volatile int x;`) | 修饰代码块或方法(如:`synchronized void method()`) | | **可见性保证** | 强制线程从主内存读取最新[^3] | 通过锁机制保证可见性[^1] | | **原子性保证** | 不保证(例如`i++`操作仍不安全)[^3] | 保证(锁内操作不可分割)[^3] | | **性能开销** | 轻量级(仅内存屏障)[^3] | 较高(涉及锁竞争上下文切换)[^3] | | **可重入性** | 不涉及 | 支持(线程可重复获取同一锁)[^2] | #### 二、典型场景分析 1. **volatile适用场景** - **状态标志位**:如多线程中控制循环退出的标志 ```java volatile boolean running = true; void stop() { running = false; } // 其他线程可立即看到修改 ``` - **单次写入的共享变量**:如配置加载完成后标记为已初始化[^3] 2. **synchronized适用场景** - **复合操作**:需要原子性保证的操作(如计数器累加) ```java public synchronized void increment() { count++; // 保证原子性 } ``` - **对象状态一致性**:需要同时修改多个关联变量时(如银行转账操作)[^2] #### 三、底层机制差异 - **volatile**:通过插入内存屏障(Memory Barrier)禁止指令重排序,强制写操作直接刷新到主内存,读操作从主内存读取[^3] - **synchronized**:基于Monitor锁机制(对象头中的Mark Word),通过`monitorenter`/`monitorexit`指令实现,包含偏向锁、轻量级锁、重量级锁的升级过程[^1] #### 四、综合使用建议 1. **优先考虑volatile**:当仅需保证可见性且操作为原子性(如boolean赋)时 2. **必须使用synchronized**:涉及非原子操作(如`i++`)或需要互斥访问资源时 3. **组合使用**:某些场景下可结合两者(如双重检查锁单例模式) ```java class Singleton { private volatile static Singleton instance; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值