首页 > 系统相关 >【Java】内存模型 volatile

【Java】内存模型 volatile

时间:2022-11-11 12:08:57浏览次数:37  
标签:Java 变量 私有 关键字 线程 内存 volatile


java堆存储对象和数组,是一块线程共享数据区,但是实际线程运行的时候,对于用到的对象都会在线程私有空间即虚拟机栈保存一个副本,为了效率。这两快内存叫主内存和工作内存。java规定所有线程对变量的操作先从主内存取得副本,然后所有的操作必须对工作内存进行(说的是堆变量)

定义了8个内存指令:

lock与unlock,与此处无关

read:把内存里的变量值拷贝到私有栈的缓存区域

load:把缓存区域里的变量值赋给线程私有变量

use:把私有变量值推入虚拟机执行引擎


assign:把虚拟机执行引擎的新值赋给私有变量

store:把私有变量的值拷贝到缓存区域

write:把缓存区域的值写回内存

如果拷贝到工作内存,必须read load,如果写回主内存,必须store write。一个线程写回前,可以多次修改本地副本变量。

以上是普通变量的情况。那么一个线程对变量的修改,可能无法让其他线程立刻看到,是一个问题。

volatile关键字就是解决线程可见性的。

通常会说,volatile是一种轻量级同步机制,个人感觉不太好,所谓同步还是和synchronized关键字比较吻合,就是线程必须一个一个来运行,而volatile关键字更多的是可见性,因此说成是种线程轻量级通讯机制更好。

那么volative是如何实现可见性?

java内存模型对被volatile关键字修饰的变量进行了特殊处理:

use指令执行前必须read和load,assign指令执行后必须store和write,如此,线程的修改是可见的。


如此以外,volatile还有另一个语义,防止指令重排序。如果两个代码是不相关的,执行的时候,顺序可能不是代码写的那样,比如先改a的值,后改b,最后可能b先被改。因为是不相关的代码,所以单线程是没有影响的,感觉不到,但是多线程环境下就会有问题,所以我们不能依赖顺序,如果想避免重排序,那么就可以加上volatile关键字,该变量就不会被冲排序。

最后,使用volatile还是同步,取决于具体的场景,哪一个的语义更加契合,如果volatile可以解决就使用volatile,效率相比同步更高

标签:Java,变量,私有,关键字,线程,内存,volatile
From: https://blog.51cto.com/u_15873544/5844085

相关文章

  • 【Java】内存区域与对象创建
    这块内容是java很基础的部分,涉及到JVM的设计原理,很久以前就看到过,这次需要区分线程私有和共享基本java的运行时数据区可以分为五大块:程序计数器,为线程私有,每一个线程都有一......
  • 【Java】split(
    java的split函数接受一个正则表达式的分隔符为参数,将string按照分隔符划分为一个数组。我们可能会忽略这个参数的要求,这里传入的分隔符并不是一个普通的字符串,而是一个正则......
  • 【Java】多线程 数目
    今天看到一篇文章,讲多线程数目的,很棒这个问题还是很容易被忽略的,就是多线程到底是为了什么?最开始学习多线程的时候,往往将多线程和性能高划等号,只要用了多线程就能提升性能,其......
  • 【Java】NoSuchMethodError
    刚开始写代码时,特别是类似web这种需要很多第三方jar包的项目,经常会遇到这个问题。这次记录下这个报错的原因。简而言之,这个报错是肯定是因为compile时方法存在,但是runtime时......
  • C语言 指针及动态内存分配
    大一学《计算系统基础》的时候,没有讲这一块的内容,导致后面遇到指针就头疼,今天特来梳理一下这块的内容。1.变量的类型类型的语言,即要求定义变量的时候必须制定类型,然后编译器......
  • 【Java】反射与单例
    双重检验与静态内部类两种方法都可以实现延迟加载的单例模式。但是无法阻止反射破坏单例,因为反射可以无视修饰权限,直接调用构造方法创建对象,下面是一个例子:packageThreadTe......
  • 【Java】序列化与单例
    之前明白了线程安全且延迟加载的单例如何写,有两种,双重检验和静态内部类。然后为了防止反射破坏单例,在私有构造方法里面加入了一个同步变量的判断,确保构造方法只调用一次。......
  • 【Java】HashMap 实现原理
    Java集合框架有两个顶级接口,一个是collection接口,另一个是map接口,hashmap便是map接口的重要实现类。首先看map接口。根据map键值对的特性,接口中必然有相关的方法,主要是:Vget......
  • 【Java】concurrentHashMap
    concurrentHashMap类引入了段的概念,读操作不需要上锁,写操作只需要获取相应的段的锁即可,而非锁定全部的数据。所以map里面是一个segment的数组,segment里面才是entry的数组。m......
  • 【Java】Map 实现类
    hashmap:遍历时顺序无法保证linkedhashmap:遍历时按照插入顺序treemap:遍历时按照大小顺序linkedhashmap实现上是继承了hashmap,多了一个双向的链表记录插入顺序,重写了迭代器,基......