在处理器的层面上,内存模型定义了一个充要条件:让当前处理器能够看到其余处理器写入到内存的数据以及其余处理器能够看到当前处理器写入到内存的数据。java
有些处理器有很强的内存模型(strong memory model),可以让全部处理器在任什么时候候任何指定的内存地址上均可以看到彻底相同的值。
而另外一些处理器则有较弱的内存模型(weaker memory model),在这种处理器中,必须使用内存屏障来刷新本地处理器缓存并使本地处理器缓存无效,目的是为了让当前处理器可以看到其余处理器的写操做或者其余处理器可以看到当前处理器的写操做。程序员
一个线程的写操做对其余线程可见这个问题是由于编译器对代码进行重排序致使的。缓存
java内存模型描述了哪些行为在多线程中是合法的,以及线程如何经过内存进行交互的。它描述了程序中的变量和从内存或者寄存器获取或存储他们的底层细节之间的关系。安全
大部分其余的语言,像C和C++,都没有被设计成直接支持多线程。这些语言对于发生在编译器和处理器平台架构的重排序行为的保护机制会严重的依赖于程序中所使用的线程库(例如pthreads),编译器,以及代码所运行的平台所提供的保障。多线程
JSR133为java语言定义了一个新的内存模型,它修复了早期内存模型的缺陷。
JSR133的目的是建立一组正式语义,这些正式语义提供了volatile、synchronzied和final如何工做的直观框架。
JSR133的目标:架构
在不少状况下,访问一个变量可能会使用不一样的顺序执行,而不是程序语义所指定的顺序执行。
编译器能够以优化的名义去改变指令顺序。在特定环境下,处理器可能会次序颠倒的执行指令。数据可能在寄存器,处理器缓冲区和主内存中以不一样的次序移动,而不是按照指定的顺序。
编译器,运行时和硬件被指望一块儿合力建立好像是顺序执行的语义的假象,这意味着在单线程的程序中,程序应该是不可以观察到重排序的影响的。可是,重排序在没有正确同步了的多线程程序中开始起做用,在这些多线程程序中,一个线程可以观察到其余线程的影响,也可能检测到其余线程将会以一种不一样于程序语义所规定的执行顺序来访问变量。框架
旧的内存模型中有几个严重的问题。这些问题很难理解,所以被普遍的违背。例如,旧的存储模型在许多状况下,不容许JVM发生各类重排序行为。
就如final字段,使用了此字段的变量是不可变的,不须要使用同步,可是就在旧的程序中final变量并无被区别对待,这觉得着同步才能保证final字段的惟一性。
旧的内存模型容许volatile变量的写操做和非volaitle变量的读写操做一块儿进行重排序,这和大多数的开发人员对于volatile变量的直观感觉是不一致的,所以会形成迷惑。性能
在Java内存模型这个语义环境下,咱们谈到“没有正确同步”,咱们的意思是:优化
当这些规则被违反的时候,咱们就说在这个变量上有一个“数据竞争”(data race)。一个有数据竞争的程序就是一个没有正确同步的程序。线程
同步有几方面的做用。首先就是互斥。
互斥:一次只有一个线程可以得到一个监视器,所以,在一个监视器上面同步意味着一旦一个线程进入到监视器保护的同步块中,其余的线程都不能进入到同一个监视器保护的块中间,除非第一个线程退出了同步块。
同步的含义比互斥更广
同步保证了一个线程在同步块以前或者在同步块中的内存写入操做以可预知的方式对其余有相同监视器的线程可见。