《深入理解Java虚拟机》之Java内存模型

一、内存模型

1.分为主内存和工作内存,分别对应虚拟机内存的堆内存、栈内存、方法区

2.8大基本操作:lock->unlock, read->load->use->assign->store->write

3.原子性、可见性、有序性

二、线程安全与高效并发:

线程调度:

1.内核线程(KLT)

2.用户线程(UT)

3.用户线程(UT)与轻量级进程(LWP)的混合模式

高效并发:

多线程环境下,线程资源的安全调用:

先行发生原则:happens before原则:

并发编程三要素:

要想并发程序正确地执行,必须要保证原子性、可见性以及有序性。只要有一个没有被保证,就有可能会导致程序运行不正确。

实现更大范围操作的原子性

可以通过synchronized和Lock来实现。由于synchronized和Lock能够保证任一时刻只有一个线程执行该代码块,那么自然就不存在原子性问题了,从而保证了原子性。

Java提供了volatile关键字来保证可见性

当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。

通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

java.util.concurrent.atomic包下提供了一些原子操作类,对基本数据类型的操作进行了封装,保证这些操作是原子性操作

CAS实现原子性操作

Compare And Swap CAS实际上是利用处理器提供的CMPXCHG指令实现的,而处理器执行CMPXCHG指令是一个原子性操作。

Volatile

保证可见性和禁止指令重排序

原理和实现机制

下面这段话摘自《深入理解Java虚拟机》:

  “观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”

  lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

  1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

  2)它会强制将对缓存的修改操作立即写入主存;

  3)如果是写操作,它会导致其他CPU中对应的缓存行无效。

请我吃辣条吧~~ 谢谢打赏
0%