并发编程(二十七)Java内存模型

98 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第25天,点击查看活动详情

1.Java内存模型

image.png

Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。

在Java中,所有实例域、静态域和数组元素都存储在堆内存中,堆内存在线程之间共享(“共享变量”这个术语代指实例域,静态域和数组元素)。局部变量(Local Variables),方法定义参数(Java语言规范称之为Formal Method Parameters)和异常处理器参数(Exception Handler Parameters)不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。

Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。

这三段引用都在介绍java内存模型。下面我用自己的语言跟大家总结一下:

java中所有的变量都是在主内存中,但是在并发情况下,某个线程想要使用这个变量,需要先把这个变量通过总线拿到自己本地内存(工作内存)中使用,此时更改变量值就会使其他线程中缓存的此变量变为无效,主内存也变为无效。这个线程把自身更改的变量值更新到主内存中。如果其他线程访问,没加volital修饰就会访问到未更新的值,加了volital修饰就会通过总线嗅探技术去访问主存中更新后的值。

上面这段以后volital关键字的时候会进行讲解。

但是volital不会解决原子性问题,那怎么去解决原子性问题呢?

这时我们就会学到原子类或者同步代码块的方式。原子类有AtomicInteger、AtomicLong等类型,使用的是CAS的方式去更新数据。同步代码块就是加锁,同一时间只有一个线程能去更改这个值。