The Java memory model describes how threads in the Java programming language interact through memory. Together with the description of single-threaded execution of code, the memory model provides the semantics of the Java programming language.
Java内存模型描述了Java编程语言中的线程如何通过内存进行交互。与对单线程执行代码的描述一起,内存模型提供了Java编程语言的语义。
The original Java memory model developed in 1995, was widely perceived as broken,[1] preventing many runtime optimizations and not providing strong enough guarantees for code safety. It was updated through the Java Community Process, as Java Specification Request 133 (JSR-133), which took effect back in 2004, for Tiger (Java 5.0).[2][3]
1995年开发的最初的Java内存模型被广泛认为是坏的, [1] 阻碍了许多运行时的优化,也没有为代码安全提供足够强大的保证。它通过Java社区进程进行了更新,作为Java规范请求133(JSR-133),早在2004年就对Tiger(Java 5.0)生效了。 [2] [3]
Context背景介绍Edit
The Java programming language and platform provide thread capabilities. Synchronization between threads is notoriously difficult for developers; this difficulty is compounded because Java applications can run on a wide range of processors and operating systems. To be able to draw conclusions about a program's behavior, Java's designers decided they had to clearly define possible behaviors of all Java programs.
Java编程语言和平台提供了线程功能。对开发者来说,线程之间的同步是出了名的困难;由于Java程序可以在各种处理器和操作系统上运行,这种困难就更大了。为了能够对程序的行为得出结论,Java的设计者决定他们必须明确定义所有Java程序的可能行为。
On modern platforms, code is frequently not executed in the order it was written. It is reordered by the compiler, the processor and the memory subsystem to achieve maximum performance. On multiprocessor architectures, individual processors may have their own local caches that are out of sync with main memory. It is generally undesirable to require threads to remain perfectly in sync with one another because this would be too costly from a performance point of view. This means that at any given time, different threads may see different values for the same shared data.
在现代平台上,代码经常不是按照编写的顺序来执行的。它被编译器、处理器和内存子系统重新排序,以达到最高性能。在多处理器架构上,各个处理器可能有自己的本地缓存,与主内存不同步。一般来说,要求线程之间保持完全同步是不可取的,因为从性能的角度来看,这样做的代价太大。这意味着,在任何时候,不同的线程可能会看到相同的共享数据的不同值。
In a single-threaded environment, it is easy to reason about code execution. The typical approach requires the system to implement as-if-serial semantics for individual threads in isolation. When an individual thread executes, it will appear as if all of the actions taken by that thread occur in the order they appear in the program, even if the actions themselves occur out of order.
在单线程环境中,推理代码的执行很容易。典型的方法是要求系统为孤立的单个线程实现if-serial语义。当一个单独的线程执行时,看起来好像该线程所做的所有动作都是按照它们在程序中出现的顺序发生的,即使这些动作本身是不按顺序发生的。
If one thread executes its instructions out of order, then another thread might see the fact that those instructions were executed out of order, even if that did not affect the semantics of the first thread. For example, consider two threads with the following instructions, executing concurrently, where the variables x and y are both initialized to 0:
如果一个线程不按顺序执行其指令,那么另一个线程可能会看到这些指令被不按顺序执行的事实,即使这并不影响第一个线程的语义。例如,考虑有两个线程同时执行以下指令,其中变量x和y都被初始化为0:
| Thread 1 课题1 | Thread 2 主题2 |
|---|---|
| x = 1; | int r1 = y; int r1 = y; |
| y = 2; | int r2 = x; int r2 = x; |
If no reorderings are performed, and the read of y in Thread 2 returns the value 2, then the subsequent read of x should return the value 1, because the write to x was performed before the write to y. However, if the two writes are reordered, then the read of y can return the value 2, and the read of x can return the value 0.
如果不进行重新排序,在线程2中对y的读取返回值2,那么随后对x的读取应该返回值1,因为对x的写入是在对y的写入之前进行的。然而,如果两个写入被重新排序,那么对y的读取可以返回值2,而对x的读取可以返回值0。
The Java Memory Model (JMM) defines the allowable behavior of multithreaded programs, and therefore describes when such reorderings are possible. It places execution-time constraints on the relationship between threads and main memory in order to achieve consistent and reliable Java applications. By doing this, it makes it possible to reason about code execution in a multithreaded environment, even in the face of optimizations performed by the dynamic compiler, the processor(s), and the caches.
Java内存模型(JMM)定义了多线程程序的可允许行为,因此描述了何时可以进行这种重新排序。它对线程和主内存之间的关系进行了执行时间限制,以实现一致和可靠的Java应用。通过这样做,它使得在多线程环境中推理代码的执行成为可能,即使面对动态编译器、处理器和缓存的优化。
The memory model记忆模型Edit
For the execution of a single thread, the rules are simple. The Java Language Specification requires a Java virtual machine to observe within-thread as-if-serial semantics. The runtime (which, in this case, usually refers to the dynamic compiler, the processor and the memory subsystem) is free to introduce any useful execution optimizations as long as the result of the thread in isolation is guaranteed to be exactly the same as it would have been had all the statements been executed in the order the statements occurred in the program (also called program order).[4]
对于单个线程的执行,规则很简单。Java语言规范要求Java虚拟机遵守线程内的as-if-serial语义。运行时(在这种情况下,通常指动态编译器、处理器和内存子系统)可以自由引入任何有用的执行优化,只要保证线程在隔离状态下的结果与所有语句在程序中出现的顺序(也称为程序顺序)执行时的结果完全相同。 [4]
The major caveat of this is that as-if-serial semantics do not prevent different threads from having different views of the data. The memory model provides clear guidance about what values are allowed to be returned when the data is read. The basic rules imply that individual actions can be reordered, as long as the as-if-serial semantics of the thread are not violated, and actions that imply communication between threads, such as the acquisition or release of a lock, ensure that actions that happen prior to them are seen by other threads that see their effects. For example, everything that happens before the release of a lock will be seen to be ordered before and visible to everything that happens after a subsequent acquisition of that same lock.[5]
这方面的主要注意事项是,as-if-serial语义并不能阻止不同线程对数据有不同的看法。内存模型对读取数据时允许返回哪些值提供了明确的指导。基本规则意味着,只要不违反线程的as-if-serial语义,单个动作可以重新排序,而意味着线程间通信的动作,如获取或释放锁 ,确保在其之前发生的动作被其他线程看到,看到其效果。例如,在释放一个锁之前发生的所有事情都会被看作是在随后获得同一锁之后发生的所有事情之前排序并可见。 [5]
Mathematically, there is a partial order called the happens-before order over all actions performed by the program. The happens-before order subsumes the program order; if one action occurs before another in the program order, it will occur before the other in the happens-before order. In addition, releases and subsequent acquisitions of locks form edges in the happens-before graph. A read is allowed to return the value of a write if that write is the last write to that variable before the read along some path in the happens-before order, or if the write is not ordered with respect to that read in the happens-before order.
在数学上,在程序执行的所有动作上有一个部分顺序,叫做发生在前的顺序。发生在前的顺序涵盖了程序的顺序;如果一个动作在程序的顺序中先于另一个动作发生,那么在发生在前的顺序中它也会先于另一个动作发生。此外,释放和随后获得的锁在发生前图中形成边。如果一个写是在读之前对该变量的最后一个写,沿着发生前顺序中的某些路径,或者如果该写在发生前顺序中没有相对于该读的顺序,则允许读返回一个写的值。
Impact影响Edit
The Java memory model was the first attempt to provide a comprehensive memory model for a popular programming language.[6] It was justified by the increasing prevalence of concurrent and parallel systems, and the need to provide tools and technologies with clear semantics for such systems. Since then, the need for a memory model has been more widely accepted, with similar semantics being provided for languages such as C++.[7]
Java内存模型是第一次尝试为一种流行的编程语言提供全面的内存模型。 [6] 它的理由是并发和并行系统的日益盛行,以及为这类系统提供具有明确语义的工具和技术的需要。从那时起,对内存模型的需求被更广泛地接受,类似的语义被提供给C++等语言。
See also另见Edit
References参考文献Edit
- ^ Pugh, William (2000). "The Java memory model is fatally flawed" (PDF). Concurrency: Practice and Experience. 12 (6): 445–455. doi:10.1002/1096-9128(200005)12:6<445::AID-CPE484>3.0.CO;2-A. Retrieved 15 July 2021.
- ^ Goetz, Brian (2004-02-24). "Fixing the Java Memory Model, Part 2" (PDF). IBM. Retrieved 2010-10-18.
- ^ Jeremy Manson and Brian Goetz (February 2004). "JSR 133 (Java Memory Model) FAQ". Retrieved 2010-10-18.
The Java Memory Model describes what behaviors are legal in multithreaded code, and how threads may interact through memory. It describes the relationship between variables in a program and the low-level details of storing and retrieving them to and from memory or registers in a real computer system. It does this in a way that can be implemented correctly using a wide variety of hardware and a wide variety of compiler optimizations.
- ^ Manson, Jeremy. "JSR-133 FAQ".Manson, Jeremy."JSR-133常见问题"。
- ^ "JLS Happens-before Order"."JLS Happens-before Order"。
- ^ Goetz, Brian (2004-02-24). "Fixing the Java Memory Model, Part 1" (PDF). IBM. Retrieved 2008-02-17.
- ^ Boehm, Hans. "Threads and memory model for C++". Retrieved 2014-08-08.
External links外部链接Edit
- Java theory and practice: Fixing the Java Memory Model, part 1 - An article describing problems with the original Java memory model.
Java理论与实践:修复Java内存模型,第一部分 - 一篇描述原始Java内存模型问题的文章。 - Java theory and practice: Fixing the Java Memory Model, part 2 - Explains the changes JSR 133 made to the Java memory model.
Java理论与实践:修复Java内存模型,第二部分 - 解释JSR 133对Java内存模型的修改。 - Java Memory Model Pragmatics (transcript)
Java内存模型实用学(实录) - The Java Memory Model links
Java内存模型的链接 - Java internal structureJava的内部结构
- JSR-133 webpageJSR-133网页
- JSR-133 FAQJSR-133常见问题
- JSR-133 implementation guideJSR-133实施指南