Java 内存模型(Java Memory Mode)理解_已改行的博客-CSDN博客_memory mode
通信是指线程之间以何种机制来交换信息，在命令式编程中，通信机制有两种:共享内存和消息传递;JAVA的并发采用的是共享内存，线程之间的通信总是隐式进行。
同步指程序中用于控制不同线程间操作发生相对顺序的机制，在共享内存并发模型中，同步是显式进行的。JAVA的内存模型 1、共享变量:分配在堆内存中的元素都是共享变量，包括实例域、静态域、数组元素。
2、非共享变量:分配在栈上的都是非共享变量，主要指的是局部变量。
1、图中的主内存用于存储共享变量，主内存是所有线程所共有的。
2、本地内存是一个抽象概念，不像主内存是真实存在的，每一个线程都有一个本地内存，用于存放该线程所使用的共享变量的副本。
如果线程A和线程B需要进行通信，则必须经过以下两个过程:
2、unlock:作用于主内存，把一个处于锁定状态的变量释放，释放后变量可以被其他线程锁定。
3、read:作用于主内存，把一个变量从主内存传输到工作内存中，用于后面的load操作。
4、load:作用于工作内存，把read操作从主内存中得到的变量值放入工作内存的变量副本中。
5、use:作用于工作内存，把变量值传递给执行引擎，每当虚拟机需要使用变量的字节码指令时将会执行这个操作。
6、assign:作用于工作内存，把从执行引擎接收到的值赋值给工作内存的变量，每当虚拟机遇到需要给该变量赋值的字节码指令时执行这个操作。
7、store:作用于工作内存，把工作内存中的一个变量值传到的主内存，以便后续的write操作。
8、write:作用于主内存，把store操作从工作内存中获取的值赋值给主内存中的变量
对于这8个操作，有如下的一个原则:
2、不允许一个线程丢弃它最近的assign操作，即变量在工作内存中的更新需要同步到主内存中。
3、不允许线程无原因地(没有发生过任何assign操作)把数据同步到主内存。
4、一个新的变量只能在主内存中产生，不能在工作内存中直接使用未被初始化的变量。
5、一个变量在同一时刻只能被一个线程lock，并且lock和unlock需要成对出现。
6、如果对一个变量执行lock操作，将会清空工作内存中此变量的值，在执行引擎使用这个变量前需要执行load或者assgin操作。
7、对一个变量执行unclock之前，必须把此变量同步到主内存中。二、重排序 重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。
2、指令级并行的重排序:如果不存在数据依赖性，处理器可以改变语句对应机器指令的执行顺序。
3、内存系统重排序:由于处理器使用缓存和缓冲区，使得加载和存储操作看上去可能是乱序执行。
数据依赖性:
上面AB这种场景就是符合as-if-serial语义的:不管怎么进行重排序，单线程程序的执行结果不能被改变。三、内存屏障 内存屏障又称内存栅栏，是一种CPU指令，用于控制特定条件下的重排序和内存可见性问题。
这样就会导致不同CPU上缓存的数据不一致问题，在多线程的程序中，就会出现一些异常行为。
目前有4种屏障:1、LoadLoad屏障:
java对内存屏障的使用有以下常见的两种:
2、使用Synchronized关键字包住的代码区域，当线程进入到该区域读取变量的信息时，保证读到的是最新的值，这是因为在同步区内对变量的写入操作，在离开同步区时将当前线程内数据刷新到主内存中。四、volatile内存语义与实现 关键字volatile是java虚拟机提供的轻量级的同步机制，只能用来修改变量，在多线程情况下保证了变量的可见性，但是不保证变量的原子性。
volatitle修饰的变量具有以下两种特性:1、可见性
而普通变量则做不到这一点，因为普通变量需要将修改的值从工作内存同步到主内存后才能被其他线程可见。
volatile变量也可以在各个线程的工作内存中存在数据不一致的情况，但是由于每次使用之前都要进行刷新，执行引擎看不到不一致的情况，因此可以认为不存在不一致的问题。
前面提高volatile不能保证原子性，下面看这段代码:
这段代码如果是正确并发的话，得到的结果应该是200000，但是我们得到的结果都是比这个值要小，且每次的结果都不一样。
我们利用下面的命令，得到increase方法的字节码如下:
可以看到在自增运算rac++是由四条字节码指令构成，这里就可以知道为什么会出现异常的原因了:第一步中getstatic指令将rac的值取到操作栈顶时，volatile保证了rac的值在此时是正确的，但是在执行第二、三步的时候，其他线程可能已经将rac的值增加了，那么在栈顶的rac的值就是过期的数据，在最后调用putstatic指令将rac同步到主内存中时，rac的值就偏小;
2、禁止指令重排序优化
2、对于不会改变程序执行结果的重排序，JMM对编译器和处理器不作要求(JMM允许这种重排序)
happens-before规则:
2、对一个锁的解锁happens-before与随后对这个锁的加锁。
3、对一个volatile域的写happens-before于任意后续对这个volatile域的读。
4、如果A happens-before B，且B happens-before C， 那么A happens-before C
6、如果线程A执行操作ThreadB.join()并且成功返回，那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
推荐文章: 全面理解Java内存模型(JMM)及volatile关键字已改行
Java 内存模型(Java Memory Mode)理解
复制链接 扫一扫 专栏目录hikaridatasource配置及使用_SpringBoot配置web访问H2
PWM Memory Mode 使用方法
PWMMemory Mode 使用方法
PWM Memory Mode 介绍和Demo Code
PWM Memory Mode 介绍:
5.12tp-11.png (84.13 KB, 下载次数: 0 )
2016-5-12 10:37 上传
关于 Memory Mode l
全局数据被认为存放在离.bss段首地址距离为32K的范围内(为什么是3
java factory mode , Java 开发设计模式之工厂模式
<br /><br />Memory Mode l:用鼠标点击 Memory Mode l的下拉箭头，会有3个 选项 :<br />Small:变量存储在内部ram里;<br />Compact:变量存储在外部ram里,使用页8位间接寻址;<br />Large:变量存储在外部Ram里,使用16位间接寻址;<br />我们一般使用Small来存储变量，就是说单片机优先把变量存储在内部ram里，如果内部ram不够了，才会存到外部去。
Compact的方式要自己通过程序来指定页的高位地址，编程比较复杂，如果
刚好在做单片机的项目，small模式下报错说空间不足，然后就换成large模式。
后来也发现了，原来之前报错是因为data区数据达到了154，超过了128，换成large后，data变成104所以才顺利通过。
N76E003开发中Keil memory mode l设置
下面说针对N76E003说说使用DATA \PDATA\ XDATA三种情况，这个都是直接编译试出来的经验，不保证完全正确。
使用Small，那么编译的时候data 数据不能大于128。