Java中的Volatile和Synchronized有何不同?

为充分理解Java中多线程同步的实现原理,必须先理解JMM。

一、Java内存模型

Java Memory Model 是为了处理并发过程中的可见性、原子性、有序性问题的。

在Java虚拟机中,堆是一个线程共享的内存区域。堆中主要存放对象的实例、静态对象、数组等。堆中存放着一些共享变量。

每条线程都会有一个属于自己的本地内存,本地内存不允许其他线程访问。本地内存中存储的是共享变量的副本。

线程A若要改变主内存中的一个变量,会先改变线程A本地内存中的值,然后再写入主内存。

在这里插入图片描述

二、线程通信和线程同步

为了让程序在多线程的情况下正确执行,我们必须关注线程通信和线程同步这两个问题

并发中的两个关键问题:

  1. 线程之间如何通信?

    1. 共享内存机制,通过共享一些公共状态,从而实现线程间信息交换。—— 隐示通信
    2. 消息传递机制,通过直接调用 wait()notify()notifyAll() 这些方法进行线程间通信。—— 显示通信
  2. 线程之间如何同步?

    同步是指程序中用于控制不同线程之间操作发生的相对顺序

    1. 在共享内存的并发模型中,同步是显示做的。程序员必须在程序中显示的调用某个方法、或某个代码段来达到线程互斥,如: Synchronized 让多个线程排队访问。
    2. 在消息传递的并发模型中,由于消息的发送必须在消息接收之前,所以同步是隐示的。

三、Volatile原理

对于申明了 Volatile 的变量进行写操作时,JVM会向处理器发送一个带Lock前缀的指令,将变量的缓存值写回主内存,在多处理器的情况下,为保证各个处理器缓存一致,就会实现缓存一致性协议(当其他处理器嗅探到缓存对应的主内存中的值发生了改变,当前缓存的旧值会失效,然后从主内存中加载新值到线程本地内存中缓存起来)

volatile使修改后的值立刻可见,从而实现同步。

通过 Volatile 实现同步,可以做到原子性、可见性,但不能做到复合操作的原子性,如: i++

自增操作是不具备原子性的,它包括读取变量的原始值、进行加1操作、写入工作内存。在多线程的情况下,自增操作的三个子操作可能会分割开执行,导致程序结果出现错误。

四、Synchronized原理

通过反编译可以看到Synchronized的原理:

在这里插入图片描述

Synchronized 原理上是实现了一个锁的机制。当方法或代码块被Synchronized修饰后,执行被修饰方法前先要获得Monitor(监视器,可理解为锁),执行完之后释放Monitor。

执行流程如下:

在这里插入图片描述

当Monitor被其他线程占用时,当前线程会进入SynchronizedQueue中等待Monitor被释放。

通过 Synchronized 实现同步,本质是实现了一个可重入锁,可以做到互斥性、可见性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值