标签:
本文通过介绍Java的新/旧内存模型,来展示Java技术的历史变迁。
Java使用的是共享内存的并发模型,在线程之间共享变量。Java语言定义了线程模型规范,通过内存模型控制线程与变量的交互,从而实现Java线程之间的通信。在JDK5之前,Java一直使用的是旧内存模型。如图1所示。变量保存在由所有线程共享的主内存中,主内存中的变量称为mastingcopy。每个线程都有一个工作内存,它保存变量的workingcopy。旧的内存模型定义了若干规则,通过这些规则来保证线程何时将主内存中的mastingcopy传送到线程的工作内存中;以及线程何时将工作内存中的workingcopy传送回主内存。旧内存模型使用8个操作来定义线程可以执行的动作。
图1 Java旧内存模型
这里的关键是,由于read操作是由主内存执行,而对应的load是由线程执行,read操作和load操作之间是松散耦合的。也就是说,主内存和线程工作内存之间的变量传递是松散耦合的。同样,由于store操作是由线程执行,而对应的write是由主内存执行,store操作和write操作之间是松散耦合的。也就是说,线程工作内存和主内存之间的变量传递是松散耦合的。旧Java内存模型对Java实现如何执行变量的读/写,加锁/解锁,以及Volatile变量的读/写,定义了非常严格的规则。这些规则非常复杂,具体详情请参考《JVM规范》,这里就不赘述了。旧Java内存模型通过这些复杂的规则,来保证多线程程序的线程之间,可以可靠地传递共享变量,从而保证多线程程序的正确性。
从JDK5开始,Java使用新的内存模型,新内存模型完全抛弃了旧内存模型的主内存和工作内存的概念,也抛弃了旧内存模型的8个内存操作。也就是说,新内存模型完全是重新设计的。
新内存模型引入了一个新的概念,叫happens-before。happens-before的概念最初由LeslieLamport在其一篇影响深远的论文(《Time,ClocksandtheOrderingofEventsinaDistributedSystem》)中提出。LeslieLamport使用happens-before来定义分布式系统中,事件之间的一个偏序关系(partialordering)。LeslieLamport在这篇论文中给出了一个分布式算法,该算法可以将该偏序关系扩展为某种全序关系。
JSR-133使用happens-before的概念来指定两个操作(这里的操作是指程序中对变量的读/写,对锁的加锁和解锁)之间的执行顺序。新内存模型定义了如下的happens-before规则。
由于两个操作可以在一个线程之内,也可以是在不同线程之间。因此JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证(如果A线程的写操作a与B线程的读操作b之间存在happens-before关系,尽管a操作和b操作在不同的线程中执行,但JMM
图2新内存模型的设计示意图
向程序员保证a操作将对b操作可见)。在新内存模型向程序员提供happens-before规则,程序员只需要与happens-before打交道即可,因此Java程序员的学习负担大大降低。同时,新内存模型允许不会改变程序结果的重排序,这可以最大限度地放松对编译器和处理器的束缚,新内存模型的执行性能比旧内存模型要好。
标签:
原文地址:http://www.cnblogs.com/leetieniu2014/p/5171447.html