Java基础:volatile详解.pdf
Java基础:volatile详解 Java基础:volatile详解问:谈谈你对volatile的理解? volatile是Java虚拟机提供的轻量级的同步机制,它有三个特性:保证可见性、不保证原子性、禁止指令重排。 1、volatile保证可见性 volatile保证可见性的作用是,多线程访问主内存的某一个资源时,如果某一个线程在自己的工作内存中修改了该资源,并写回主内存,那么JMM内存模型应该要通知其他线程来从新获取最新的资源,来保证最新资源的可见性。 1.1、什么是JMM模型? JMM(Java内存模型,Java Memory Model)本身是一种抽象的概念,并不真实存在。它描述的是一组规则或规范,通过这组规范,定了程序中各个变量的访问方法。JMM关于同步的规定: 1)线程解锁前,必须把共享变量的值刷新回主内存; 2)线程加锁前,必须读取主内存的最新值到自己的工作内存; 3)加锁解锁是同一把锁; 由于JVM运行程序的实体是线程,创建每个线程时,JMM会为其创建一个工作内存(有些地方称为栈空间),工作内存是每个线程的私有数据区域。Java内存模型规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问。但线程对变量的操作(读取、赋值等)必须在工作内存中进行。因此首先要将变量从主内存拷贝到自己的工作内存,然后对变量进行操作,操作完成后再将变量写会主内存中。 用一个卖票系统来进行举例: 1)如下图,此时卖票系统后端只剩下1张票,并已读入主内存中:ticketNum=1。 2)此时网络上有多个用户都在抢票,那么此时就有多个线程同时都在进行买票服务,假设此时有3个线程都读入了目前的票数:ticketNum=1,那么接着就会买票。 3)假设线程1先抢占到cpu的资源,先买好票,并在自己的工作内存中将ticketNum的值改为0:ticketNum=0,然后再写回到主内存中。此时,线程1的用户已经买到票了,那么线程2,线程3此时应该不能再继续买票了,因此需要系统通知线程2,线程3,ticketNum此时已经等于0了:ticketNum=0。如果有这样的通知操作,你就可以理解为就具有可见性。 1.2、volatile保证可见性的代码验证 在1.1中,已经基本理解了可见性的含义,接下来用代码来验证一下,volatile确实可以保证可见性。 1.2.1、无可见性代码验证 首先先验证下,不使用volatile,是不是就是没有可见性。 代码示例: ``` package com.koping.test; import java.util.concurrent.TimeUnit; class MyData{ int number = 0; public void add10() { this.number += 10; } } public class VolatileVisibilityDemo { public static void main(String[] args) { ... ``` 运行结果如下图,可以看到虽然线程0已经将number的值改为了10,但是主线程还是在循环中,因为此时number不具有可见性,系统不会主动通知。 1.2.2、volatile保证可见性验证 通过使用volatile关键字,来验证volatile确实可以保证可见性。 代码示例: ``` package com.koping.test; import java.util.concurrent.TimeUnit; class MyData{ volatile int number = 0; public void add10() { this.number += 10; } } public class VolatileVisibilityDemo { public static void main(String[] args) { ... ``` 通过运行结果可以看到,使用volatile关键字后,主线程可以正确地获取最新的number值,此时系统可以正确地通知其他线程。 总结来说,volatile保证可见性是通过JMM内存模型来实现的,volatile关键字可以确保多线程之间的可见性,从而避免一些不必要的错误。
剩余14页未读,继续阅读
- 粉丝: 2500
- 资源: 5734
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助