IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java 并发编程 请谈谈你对volitile的理解 -> 正文阅读

[Java知识库]java 并发编程 请谈谈你对volitile的理解

1. volatile是什么

他是JVM提供的轻量级2同步机制

1.保证可见性

2.不保证原子性

3.禁止指令重排(保证有序性)

2.JMM内存模型之可见性

JMM本身是一种抽象的概念不是真实存在的,它描述的一组规则或者规范,通过这组规范定义了程序中的各个变量(包括实例字段,静态字段,和构成数组的元素)的访问方式。

JMM关于同步的规定:

1.线程解锁前,必须把共享变量的值刷新回主内存

2.线程枷锁前,必须读取主内存的最新值到自己的工作内存

3.枷锁解锁是同一把锁

由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),工作内存是每个线程的私有数据区域,而Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,各个线程中的工作内存中存储着主内存中的变量副本拷贝,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成,其简要访问过程如下图:

可见性

通过前面对JMM的介绍,我们知道各个线程对主内存中共享变量的操作都是各个线程各自拷贝到自己的工作内存中进行操作后写回到主内存中去。

这就可能存在一个线程AAA修改了共享变量X的值还未写回到主内存时,另外一个线程BBB又对主内存同一个变量X进行操作,但此时A线程工作内存中共享变量x对B来说并不可见,这中工作内存和主内存同步延迟现象就造成了可见性问题。

可见性的代码验证说明

import java.util.concurrent.TimeUnit;

/**
?* 假设是主物理内存
?*/
class MyData {

? ? //volatile int number = 0;
? ? int number = 0;

? ? public void addTo60() {
? ? ? ? this.number = 60;
? ? }
}

/**
?* 验证volatile的可见性
?* 1. 假设int number = 0, number变量之前没有添加volatile关键字修饰
?*/
public class VolatileDemo {

? ? public static void main(String args []) {

? ? ? ? // 资源类
? ? ? ? MyData myData = new MyData();

? ? ? ? // AAA线程 实现了Runnable接口的,lambda表达式
? ? ? ? new Thread(() -> {

? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + "\t come in");

? ? ? ? ? ? // 线程睡眠3秒,假设在进行运算
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? TimeUnit.SECONDS.sleep(3);
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? // 修改number的值
? ? ? ? ? ? myData.addTo60();

? ? ? ? ? ? // 输出修改后的值
? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + "\t update number value:" + myData.number);

? ? ? ? }, "AAA").start();

? ? ? ? // main线程就一直在这里等待循环,直到number的值不等于零
? ? ? ? while(myData.number == 0) {}

? ? ? ? // 按道理这个值是不可能打印出来的,因为主线程运行的时候,number的值为0,所以一直在循环
? ? ? ? // 如果能输出这句话,说明AAA线程在睡眠3秒后,更新的number的值,重新写入到主内存,并被main线程感知到了
? ? ? ? System.out.println(Thread.currentThread().getName() + "\t mission is over");

? ? }
}


?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-06 10:55:43  更:2022-05-06 10:58:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:08:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码