一、java的内存模型
1、内存模型简介
(1)不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的
(2)线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型,要解决两个主要的问题:可见性和有序性。
(3)我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节
2、可见性
前提:Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程共享的。当new一个对象的时候,也是被分配在主内存中,每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本。
当线程操作某个对象时,执行顺序如下:
(1) 从主存复制变量到当前工作内存 (read and load)
(2) 执行代码,改变共享变量值 (use and assign)
(3) 用工作内存数据刷新主存相关内容 (store and write)
3、有序性
如果线程工作内存中没有该变量,则直接从主存中拷贝过来一个副本,即read-load,同一线程对该字段又再次引用时候,有两种情况,一是从主存中取(即read-load-use),二是直接从副本中取(use)。
对于一个多次引用该字段,并且进行asign,它会将值指定给工作内存中的变量副本(assign),完成后这个变量副本会同步到主存储区(store-write),至于何时同步过去,根据JVM实现系统决定。
二、synchronize和valotile
(1)synchronize
一个线程执行临界区代码过程如下:
1 获得同步锁
2 清空工作内存
3 从主存拷贝变量副本到工作内存
4 对这些变量计算
5 将变量从工作内存写回到主存
6 释放锁
可见,synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性。
(2)valotile
是轻量级的同步,为什么这么说,因为volatile只能保证多线程的内存可见性,不能保证多线程的执行有序性。任何被volatile修饰的变量,都不拷贝副本到工作内存,任何修改都及时写在主存。因此对于Valatile修饰的变量的修改,所有线程马上就能看到。