JAVA高并发(二)

2021-01-14  本文已影响0人  花开此时海

    要了解高并发以及相关的问题,首先需要了解JAVA内存模型。

    一般来说,线程之间通信的方式包括两种,共享内存和消息传递。由于多种操作系统存在差异,不同的架构系统存在不同的内存模型,为了实现平台一致性,JMM应运而生,JMM实际并不真实存在,本身是种概念,主要解决的是由于多线程通过共享内存进行通信时,由于本地内存的数据不一致或重排序而导致的并发问题,JMM内存模型抽象如下:

    首先解释一下本地内存,实际上线程本不存在本地内存,而是由计算机硬件架构导致的,在现代多核处理器计算机中,为了提升系统的运算效率,处理器并不直接与主内存进行内存的读写操作,而是通过寄存器,高速缓存,写缓冲器,无效队列等进行内存的读写操作的,而这些部件可以视为线程的本地内存,即主内存的副本。

    其次解释一下重排序,JAVA代码从编写到执行,首选经过编译器的静态编译为class文件,再经过JIT编译器编译为机器码,以及处理器执行指令,一般来说静态编译的字节码和我们编写的代码顺序是保持一致的,而编译器再将字节码转换为机器码的过程中,出于性能的考虑,在其认为不影响程序正确性的情况下会执行指令重排序,除此之外,处理器也可能在执行过程中进行指令重排序,现代计算机为了提升执行效率,往往不是按照给定顺序进行逐一执行的,而是动态调整顺序,指令就绪就先执行,这样就会导致指令的乱序执行,另外处理器还有一种猜测执行的技术,即可能导致if语句优先条件语句的执行。而存储系统也会导致内存重排序。

    as-if-serial:该语义即为在单线程下保证代码在重排序后不影响程序的正确性.这也是JIT编译器和处理器进行重排序需要遵守的规则,但是并不保证多线程下的代码正确性。

    内存屏障:as-if-serials仅仅保证了单线程下的指令的有序性,在多线程下的内存重排序与可见性则是通过内存屏障来保证的,在计算机中,读内存操作称之为Load,写内存操作为store,因此内存重排序理论上为四种,LoadStore,LoadLoad,StoreLoad,StoreStore.

    Store屏障:强制所有在store屏障指令之前的store指令,都在该store屏障指令执行之前被执行,并把store缓冲区的数据都刷到CPU缓存.

    Load屏障:强制所有在load屏障指令之后的load指令,都在该load屏障指令执行之后被执行,并且一直等到load缓冲区被该CPU读完才能执行之后的load指令。

    happens-before:该原则保证在多线程的处理下,一个操作happens-before另一个操作,则该操作的结果一定是可见的。实际上并不阻止重排序,在不影响操作结果的情况下.

上一篇下一篇

猜你喜欢

热点阅读