java内存模型

1、cpu的多级缓存

由于cpu跟内存技术不匹配,cpu运行速度快,内存跟不上,出现了高速缓存。
当cpu需要运算时,内存将数据发送给高速缓存,然后cpu从高速缓存中拿到数据后,进行读写操作完毕后,高速缓存将数据写回到内存中。

java内存模型_第1张图片
由于cpu发展过快,一级缓存已经无法满足,就出现了二级、三级缓存

2.缓存一致性

对于多核cpu来说,每一个cpu查找数据时,先从一级换成中查找,找不到从二级缓存中找,还找不到就从三级缓存找(如果有三级缓存的话),最后从主存查找。
每个cpu从各自的缓存中,多核cpu就有多套缓存,这样就导致了缓存不一致现象。
怎么解决呢?出现了缓存一致性协议,它保证了每个缓存中的变量副本是一致的。
最著名的是Intel的MESI协议,它的核心思想是:当cpu写数据时,发现该数据是共享变量,就把其他cpu对应缓存中该变量副本置为失效,然后将变量写入到内存中。其他cpu使用变量时发现该变量失效了,就从内存中重新读取该变量。

3、内存模型

内存模式是一种规范,通过读写操作的规范,保证了指令执行的正确性。
它能解决多核cpu缓存、多线程并发等问题。
java的内存模型是符合内存模型规范的,并且提供了一些关键字比如synchronized、volatile等,保证了线程之间原子性、可见性、有序性。
java内存模型也只是一个规范,底层定义了一些关键字比如synchronized、volatile等去实现所说的规范

3.1 原子性

对于数据库来说,原子性就是“要么都执行,要么都回滚”
对于多线程来说,原子性就是“执行操作不能中断,不可拆分”

为什么会出现原子性呢?
这就要从cpu时间片说起了。
对于一台单核cpu计算机,每开一个软件就是一个任务,当开多个软件时,我们看起来是可以同时使用这些软件的,其实是将cpu的使用时间分成长短差不多的时间片,然后分配给这些任务,某个任务的cpu时间片到了就切换到下一个任务。由于这些时间片分割的足够短,可能只有几毫秒,这样我们看起来,这些软件是同时运行的,是感觉不到切换的。

对于多线程来说,其中一个线程执行操作到一半,cpu时间片就到了,就需要暂停,另一个线程开始执行操作。
经典例子就是++i;这个操作是需要读(从内存中读)、改(对i进行+1操作)、写(将i修改后的值写入到内存中)三个步骤,其中一个线程如果执行了读改(比如i=0,改后i=1),cpu切换到另一个线程中,另一个线程执行完读、改、写后,,第一个线程继续执行写操作,就将i=1写入到内存中了。

3.2 可见性

多线程同时访问一个变量,一个线程能立马能看到另一个线程修改后的该变量值

3.3有序性

对于计算机硬件,它进行了指令重排和处理器的优化,这样就导致一些操作的结果出现错误。
比如++i,它可能会被优化为 先读i,然后写入i,最后在进行i+1操作

针对多线程的原子性、可见性、有序性问题,java内存模型设计了一些关键字
volatile就是针对可见性的,而synchronized则解决了原子性、可见性、有序性问题

引用:
1、hollis的八股文

你可能感兴趣的:(java基础,java,java,开发语言)