JMM模型

(1).计算机底层CPU模型

          如果三个cup的线程都从主内存中取到X=1的值进行计算,此时就要保证数据的一致性,目前CPU使用MESI(缓存一致性协议)来控制,如果CPU1想从主内存拿到X=1这个值想要计算,首先寄存器会在本身寻找如果没有,则去缓存L1,L2,L3中依次寻找,如果都没有则去主内存中拿到CPU缓存中最终放入寄存器计算,拿到后将X标注为E独占状态,标记为E的同时又开启了总线嗅探机制会时刻监听内存中X值,如果此时CPU2去拿主内存中的X=1在经过总线时会被监听到,此时CPU1会将缓存行中的X状态改为S共享状态,CPU2读到值后也会标注为S共享状态,如果CPU1把X=1进行计算后,得到X=2此时CPU1会把X的缓存行锁住并且状态置M修改,在把X=2回写到主内存中消息经过总线会被CPU2监听机制监听到此时CPU2会把之前读到的X=1置为I失效(大写字母哎),然后接着CPU1会把X=2回写到主内存中回写完以后又会把CPU1中的X=2置为E独占状态,如果CPU2还访问得到X就要把之前存在缓存中的X=1丢弃,然后去主存  中重新得到X=2,读完之后CPU1嗅探到了CPU2读到主存中的数据此时CPU1与CPU2又会把自己的状态变成共享S了。

(2)MESI缓存一致性协议

(3)线程分为用户级别和内核级别线程,比如java虚拟机 PS 或者播放器这些进程他们开启一些线程,这些线程被称作虚假线程不能真实操作CPU,他们需要被内核级线程提供的接口接收转换,真正接触CPU的是内核级线程,CPU有Ring0,Ring3这些特权级别,如果想操作CPU的话只能是Ring0级别也就是说只有内核级线程才能接触到他,用户级线程是用的ring3级别


(4)线程的生命状态


(5)线程执行切换(时间片算法)底层模型

1、首先CPU在执行不用线程任务的话会有一种时间片算法,也就是把一个任务分成一个一个的时间片来执行。

2、在时间片的切换过程中,如果当前CPU正在执行时间片A执行完要切换到时间片B,就要把A的当前的所有状态(指令,程序指针,中间数据)都回写到主内存中的TSS(任务状态断)中,之后开始执行时间片B执行完之后如果下一个被执行的是A的话会重新把A的状态从TSS中读出来接着继续执行,

(6)JMM模型如何保证操作的 原子性和有序性和可见性

     1.数据可见性,比如两个线程在访问同一块内存区域数据的时候如下图代码,当线程A开始执行的时候会先把数据从主内存中Load进工作副本在副本中复制一份主内存中的数据,然后use推进CPU因为A线程这里做了一个死循环,当前线程就一直在执行这个操作,一直不断的use推进CPU由于他优先级比较高所以会一直占用线程着A,此时线程B开始执行同样从主内存load后推入CPU把值改为ture后在assign进工作内存把值改为true后写回主内存把主内存的值也改为true,此时线程A还在进行循环不断推进中,无法感知到值被改为true,如果在load方法中while循环里加上一把锁这样会使线程A可能会阻塞从而导致线程的执行权被抢走,因为是时间片算法在抢走时会把状态回写到主内存中等到再获CPU的执行权再读进工作内存中,这个操作可能会导致工作内存会重新读取主内存中值,此时值是被线程B改过了所以此时可以保证数据一致。

     2.如果在initflag变量前加上关键字,volatile就会开启缓存一致性协议来保持线程间不同工作副本的数据可见性


     3.有序性:操作要保持有序性是因为JVM在执行一些操作时候如果交换执行顺序不影响(单线程)最终结果的时候,可能会把执行顺序改变但在多线程情况下情况比较复杂,比如单例模式双重检查锁就存在这个问题,可以加上volatie关键字禁止cpu和jvm对当前操作的指令重排。

       3.1指令重排是发生在那个阶段呢?

        答: 执行器编译阶段也就是加载class文件编译成字节码的时候和cpu运行时也就是cpu执行汇编指令时执行的。

       3.2通过插入屏障的方式来限制指令重排,屏障有 storeload写读屏障,loadstore读写屏障,loadload读读屏障,storestore写写屏障,如下图第一个a=1是volatile写操作,第二个x=b是先volatile读操作再普通写操作,jvm会在中间插入写读屏障保证不被指令重排


       3.3如果不使用volatile的时候怎么禁止指令重排呢?

       答:java提供了一个类 Unsafe 的fullFence(),loadFence(),storeFence(),三个方法手动添加内存屏障。

    4.原子性:volatie不能保证操作的原子性,原子性得通过关键字保证,原子性指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。比如i++就不是一个原子性操作。


   5.总线风暴:总线风暴的产生就是从主内存到工作内存中如果开启了缓存一致性协议的话,线程嗅探过多或者频繁访问工作内存过多就对引起,这时读写效率都将会大大下降

你可能感兴趣的:(JMM模型)