JMM 定义
JMM即Java内存模型(Java memory model),在JSR133里指出了JMM是用来定义一个一致的、跨平台的内存模型,是缓存一致性协议,用来定义数据读写的规则。
线程堆栈上面分别有什么?
线程栈
- 所有基本类型的局部变量
- 局部变量只能通过变量副本在线程间传递
线程执行时,方法的所有基本类型的局部变量会直接存在栈上面,而基本类型的包装类(Byte、Long)和自定义的类这一类的对象直接方法堆里面,栈中使用直接该对象的局部变量副本
堆
- 所有引用类型的变量的对象都存在堆上
- 线程中使用的是该引用类型对象的局部变量副本
内存可见性
多个线程使用同一共享对象时,没有正确使用volatile和同步,则其中一个线程更新数据,其他线程不可见
如图所示:
左边的cpu运行一个线程将共享对象复制一份到缓存中,并修改它,但是并没有更新到主内存,所以对于右边的线程来说是不可见的。
在内存可见,就需要更改后将更新后的值写回主内存中,Java的volatile
关键字可以保证每次更新后都写回主内存。
竞态条件
多个线程同时更新共享对象,导致出现竞态问题。
高并发同时执行累加操作,A线程获取count值并加一后,还没回写,B已经获取count值,导致执行了两次,但是count 值为1。
怎么保证在高并发下还能累加呢?那就使用 java synchronized
,可以在方法上加上synchronized
关键字,也可以在累加代码块使用synchronized
,它保证每次只有一个线程去执行方法或者代码块,从而保证数据的准确性。
synchronized 虽然保证了顺序执行,但是这种方式在高并发用不好可能会导致效率很差。