http://www.cs.umd.edu/~pugh/java/memoryModel/

http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf

中文版

1 Introduction

JavaTM virtual machines support multiple threads of execution.

java虚拟机支持多线程执行。


Threads are represented by the Thread class.

线程Thread类表示


The only way for a user to create a thread is to create an object of this class;

用户创建线程的唯一方法是创建此类的对象;


each thread is associated with such an object.

每个线程都这样的对象关联


A thread will start when the start() method is invoked on the corresponding Thread object.

当对相应的线程对象调用start()方法时,线程将启动。


The behavior of threads, particularly when not correctly synchronized, can be confusing and
counterintuitive.

线程的行为,特别是在未正确同步时,可能会令人困惑和违反直觉的。


This specification describes the semantics of multithreaded programs written in the JavaTM programming language;

本规范描述了用 JavaTM 编程语言编写的多线程程序的语义


it includes rules for which values may be seen by a read of shared memory that ** is updated by multiple threads.**

它包括可以通过读取共享内存看到的值的规则,该共享内存由多个线程更新。


As the specification is similar to the memory models for different hardware architectures, these semantics are referred to as the JavaTM memory model.

由于规范类似于不同硬件架构的内存模型,这些语义被称为 JavaTM 内存模型。


These semantics do not describe how a multithreaded program should be executed.

这些语义没有描述应该如何执行多线程程序


Rather, they describe the behaviors that multithreaded programs are allowed to exhibit.

相反,它们描述了多线程程序被允许展示的行为。


Any execution strategy that generates only allowed behaviors is an acceptable execution strategy.

任何只生成允许行为的执行策略都是可接受的执行策略。

1.1 Locks

There are multiple mechanisms for communicating between threads.

线程之间有多种通信机制


The most basic of these methods is synchronization, which is implemented using monitors.

这些方法中最基本的是同步,它是使用监视器实现的。


Each object is associated with a monitor, which a thread can lock or unlock.

每个对象都与一个监视器相关联,线程可以锁定或解锁监视器。


Only one thread at a time may hold a lock on a monitor.

一次只有一个线程**可以锁定监视器。


Any other threads attempting to lock that monitor are blocked until they can obtain a lock on that monitor.

任何其他试图锁定该监视器的线程都会被阻塞直到他们可以获得该监视器上的锁定。


A thread t may lock a particular monitor multiple times;

一个线程 t 可能会锁定一个特定的监视器多次


each unlock reverses the effect of one lock operation.

每次解锁反转一次锁定操作的效果。


The synchronized statement computes a reference to an object;

同步语句计算对对象的引用;


it then attempts to perform a lock action on that object’s monitor and does not proceed further until the lock action has successfully completed.

然后它会尝试在该对象的监视器上执行锁定操作,并且不会继续进行,直到锁定操作成功完成。


After the lock action has been performed, the body of the synchronized statement is executed.

锁定动作执行完毕后,同步语句的主体将被执行。


If execution of the body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.

如果主体的执行完成,无论是正常的还是突然的,都会在同一个监视器上自动执行解锁操作。


A synchronized method automatically performs a lock action when it is invoked;

同步方法在调用时自动执行锁定操作


its body is not executed until the lock action has successfully completed.

在锁定操作成功完成之前,它的主体不会被执行


If the method is an instance method, it locks the monitor associated with the instance for which it was invoked (that is, the object that will be known as this during execution of the body of the method).

如果该方法是一个实例方法,它会锁定与调用它的实例相关联的监视器(即,在方法体执行期间将被称为 this 的对象)。


If the method is static, it locks the monitor associated with the Class object that represents the class in which the method is defined.

如果方法是静态的,它会锁定与 Class 对象关联的监视器,该对象表示定义该方法的类。


If execution of the method’s body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.

如果方法主体的执行已经完成,无论是正常的还是突然的,都会在同一个监视器上自动执行解锁操作。


The semantics neither prevents nor requires detection of deadlock conditions.

语义既不防止也不要求检测死锁条件。


Programs where threads hold (directly or indirectly) locks on multiple objects should use conventional techniques for deadlock avoidance, creating higher-level locking primitives that don’t deadlock, if necessary.

线程持有(直接或间接)多个对象锁的程序应该使用传统技术来避免死锁,如有必要,创建不会死锁的更高级别的锁定原语。


Other mechanisms, such as reads and writes of volatile variables and classes provided in the java.util.concurrent package, provide alternative mechanisms for synchronization.

其他机制(例如 java.util.concurrent 包中提供的 volatile 变量和类的读取和写入)提供了替代的同步机制。

1.2 Notation in Examples

The Java memory model is not fundamentally based in the object oriented nature of the Java programming language.

Java 内存模型从根本上不是基于 Java 编程语言的面向对象特性。


For conciseness and simplicity in our examples, we often exhibit code fragments without class or method definitions, or explicit dereferencing.

为了在我们的示例中简洁和简单,我们经常展示没有类或方法定义或显式取消引用的代码片段。


Most examples consist of two or more threads containing statements with access to local variables, shared global variables or instance fields of an object.

大多数示例由两个或多个线程组成,其中包含可以访问局部变量、共享全局变量或对象实例字段的语句。


We typically use variables names such as r1 or r2 to indicate variables local to a method or thread. Such variables are not accessible by other threads.

我们通常使用诸如 r1 或 r2 之类的变量名称来指示方法或线程的局部变量。其他线程无法访问此类变量。

2 Incorrectly Synchronized Programs Exhibit Surprising Behaviors 不正确同步的程序表现出令人惊讶的行为

The semantics of the Java programming language allow compilers and microprocessors to perform optimizations that can interact with incorrectly synchronized code in ways that can produce
behaviors that seem paradoxical.

Java 编程语言的语义允许编译器和微处理器执行优化,这些优化可以与不正确同步的代码交互,从而产生
看似自相矛盾的行为。


Consider, for example, Figure 1. 例如,考虑图1。

This program uses local variables r1 and r2 and shared variables A and B

该程序使用局部变量 r1 和 r2 以及共享变量 A 和 B


It may appear that the result r2 == 2, r1 == 1 is impossible.

看起来结果 r2 == 2, r1 == 1 是不可能的


Intuitively,either instruction 1 or instruction 3 should come first in an execution

直观地说,指令 1 或指令 3 应该在执行中首先出现


If instruction 1 comes first,it should not be able to see the write at instruction 4.

如果指令1先出现,它应该看不到指令4处的写操作。


If instruction 3 comes first, it should not be able to see the write at instruction 2.

如果指令3先出现,它应该看不到指令2处的写操作。


If some execution exhibited this behavior, then we would know that instruction 4 came before instruction 1, which came before instruction 2, which came before instruction 3, which came before instruction 4.

如果某些执行表现出这种行为,那么我们就会知道指令 4 出现在指令 1 之前,指令 1 出现在指令 2 之前,指令 2 出现在指令 3 之前,指令 3 出现在指令 4 之前。


This is, on the face of it, absurd. 从表面上看,这是荒谬的。


However, compilers are allowed to reorder the instructions in either thread, when this does not
affect the execution of that thread in isolation.

但是,允许编译器重新排序任一线程中的指令,如果这不单独影响该线程的执行。


If instruction 1 is reordered with instruction 2, then it is easy to see how the result r2 == 2 and r1 == 1 might occur.

如果指令 1 与指令 2 重新排序,那么很容易看出结果 r2 == 2 和 r1 == 1 可能如何发生。


To some programmers, this behavior may seem “broken”.
对于一些程序员来说,这种行为可能看起来“坏了”。


However, it should be noted that this code is improperly synchronized:
但是,应该注意的是,此代码没有正确同步:

  • there is a write in one thread, 一个线程中有一个写入
  • a read of the same variable by another thread, 另一个线程读取相同的变量
  • and the write and read are not ordered by synchronization. 并且写入和读取不是按同步排序的。

When this occurs, it is called a data race. 发生这种情况时,称为数据竞争。


When code contains a data race, counterintuitive results are often possible.

当代码包含数据竞争时,通常可能会出现违反直觉的结果。


Several mechanisms can produce the reordering in Figure 1

有几种机制可以产生图 1 中的重新排序


The just-in-time compiler and the processor may rearrange code.

即时编译器和处理器可以重新排列代码。


In addition, the memory hierarchy of the architecture on which a virtual machine is run may make it appear as if code is being reordered.

此外,运行虚拟机的体系结构的内存层次结构可能使其看起来好像代码正在重新排序。


For the purposes of simplicity, we shall simply refer to anything that can reorder code as being a compiler

为了简单起见,我们将简单地将任何可以重新排序代码的东西称为编译器


Source code to bytecode transformation can reorder and transform programs, but must do so only in the ways
allowed by this specification.

源代码到字节码的转换可以重新排序和转换程序,但只能在方式本规范允许。


Another example of surprising results can be seen in Figure 2.

另一个令人惊讶的结果示例如图 2 所示。

This program is also incorrectly synchronized; 这个程序也同步不正确;


it accesses shared memory without enforcing any ordering between those accesses.

它访问共享内存而不强制这些访问之间的任何顺序。


One common compiler optimization involves having the value read for r2 reused for r5:

一种常见的编译器优化涉及将r2读取的值重新用于r5:


they are both reads of r1.x with no intervening write. 它们都是对r1.x的读取,中间没有写入。

r2 和 r5 都是对 r1.x值的读取。


Now consider the case where the assignment to r6.x in Thread 2 happens between the first
read of r1.x and the read of r3.x in Thread 1.

现在考虑在线程 2 中对 r6.x 的赋值发生在第一个线程之间的情况在线程 1 中读取 r1.x 和读取 r3.x。


If the compiler decides to reuse the value of r2 for the r5, then r2 and r5 will have the value 0, and r4 will have the value 3.

如果编译器决定为 r5 重用 r2 的值,则 r2 和 r5 的值为 0,而 r4 的值为 3。


From the perspective of the programmer, the value stored at p.x has changed from 0 to 3 and then changed back.

从程序员的角度来看,p.x 中存储的值已经从 0 变为 3,然后又变回来了。


Although this behavior is surprising, it is permitted by most JVM implementations.

尽管这种行为令人惊讶,但大多数 JVM 实现都允许这样做。


However,it was forbidden by the original Java memory model in the JLS and JVMS:

但是,它被 JLS 和 JVMS 中的原始 Java 内存模型所禁止:


this was one of the first indications that the original JMM needed to be replaced.

这是最初的 JMM 需要更换的迹象之一。

3 Informal Semantics

A program must be correctly synchronized to avoid the kinds of counterintuitive behaviors that can be observed when code is reordered.

程序必须正确同步以避免在重新排序代码时可以观察到的违反直觉的行为。


The use of correct synchronization does not ensure that the overall behavior of a program is correct.

使用正确的同步并不能确保程序的整体行为是正确的。


However, its use does allow a programmer to reason about the possible behaviors of a program in a simple way;

但是,它的使用确实允许程序员以简单的方式推断程序的可能行为。


the behavior of a correctly synchronized program is much less dependent on possible reorderings.

正确同步的程序的行为对可能的重新排序的依赖性要小得多。


Without correct synchronization, very strange, confusing and counterintuitive behaviors are possible.

如果没有正确的同步,可能会出现非常奇怪、令人困惑和违反直觉的行为。


There are two key ideas to understanding whether a program is correctly synchronized:
理解程序是否正确同步有两个关键思想:


Conflicting Accesses Two accesses (reads of or writes to) the same shared field or array element
are said to be conflicting if at least one of the accesses is a write.

访问冲突对同一共享字段或数组元素的两次访问(读取或写入) 如果至少一个访问是写,则称为冲突。


Happens-Before Relationship Two actions can be ordered by a happens-before relationship.

Happens-Before 关系,两个行为可以由happens-before 关系排序


If one action happens-before another, then the first is visible to and ordered before the second.

如果一个动作 happens-before 另一个, 然后第一个对第二个可见并在第二个之前排序。


It should be stressed that a happens-before relationship between two actions does not imply that
those actions must occur in that order
in a Java platform implementation.

应该强调的是,两个动作之间的happens-before关系并不意味着在 Java 平台实现中,这些操作必须按此顺序发生。


The happens-before relation mostly stresses orderings between two actions that conflict with each other, and defines when data races take place.

happens-before关系主要强调两个相互冲突的动作之间的顺序,并定义何时发生数据竞争。


There are a number of ways to induce a happens-before ordering,including:

有许多方法可以引发happens-before顺序,包括:

  1. Each action in a thread happens-before every subsequent action in that thread. 线程中的每个动作happens-before 该线程中的每个后续操作。
  2. An unlock on a monitor happens-before every subsequent lock on that monitor. 一个监视器的解锁 happens-before 每一个后续的锁定。
  3. A write to a volatile field happens-before every subsequent read of that volatile. volatile字段的写入 happens-before 每一个后续的读。
  4. A call to start() on a thread happens-before any actions in the started thread. 在线程上调用 start() happens-before 已启动线程中的任何操作。
  5. All actions in a thread happen-before any other thread successfully returns from a join() on that thread. 线程中的所有操作都happen-before 任何其他线程从该线程上的 join() 成功返回之前。
  6. If an action a happens-before an action b, and b happens-before an action c, then a happens-before c. 如果一个动作a happens-before b,并且 b happens-before c ,那么 a happens-before c。

Happens-before is defined more thoroughly in Section 5. Happens-before在第 5 节中有更彻底的定义。


When a program contains two conflicting accesses that are not ordered by a happens-before
relationship, it is said to contain a data race.

当一个程序包含两个冲突的访问,这些访问没有被happens-before排序关系,被称为包含数据竞争。


A correctly synchronized program is one that has no data races (Section 3.1 contains a subtle but important clarification).

正确同步的程序是没有数据竞争的程序(第 3.1 节包含一个微妙但重要的说明)。


A more subtle example of incorrectly synchronized code can be seen in Figure 3, which shows
two different executions of the same program, both of which contain conflicting accesses to shared
variables X and Y.

图 3 中可以看到一个更微妙的错误同步代码示例,它显示同一程序的两次不同执行,两者都包含对共享的冲突访问变量 X 和 Y。


The two threads in the program lock and unlock a monitor M1. 程序中的两个线程锁定和解锁监视器 M1。


Thread 1 acquires lock first;Accesses to X are ordered by happens-before
线程1先获取锁,对x变量的访问被 happens-before 排序。
Thread 2 acquires lock first;Accesses to X not ordered by happens-before
线程2先获取锁,对x变量的访问未被 happens-before 排序。


In the execution shown in Figure 3a, there is a happens-before relationship between all pairs of conflicting accesses.

在图 3a 所示的执行中,所有冲突访问对之间存在happens-before的关系。


However, in the execution shown in Figure 3b, there is no happens-before ordering between the
conflicting accesses to X.

然而,在图 3b 所示的执行中,在对 X 的冲突访问之间没有happens-before的排序。


Because of this, the program is not correctly synchronized. 因此,程序未正确同步。


If a program is correctly synchronized, then all executions of the program will appear to be
sequentially consistent.


如果一个程序正确同步,那么程序的所有执行都将看起来是顺序一致的。

This is an extremely strong guarantee for programmers. 这对程序员来说是一个极其有力的保证。


Once programmers are able to determine that their code contains no data races, they do not need to worry that reorderings will affect them.

一旦程序员能够确定他们的代码不包含数据竞争,他们就不必担心重新排序会影响他们。

3.1 Sequential Consistency 顺序一致性

Sequential consistency is a very strong guarantee that is made about visibility and ordering in an execution of a program.

顺序一致性是一个非常强大的保证,它是关于程序执行中的可见性和顺序的。


Within a sequentially consistent execution, there is a total order over all individual actions (such as reads and writes) which is consistent with the order of the program.

在顺序一致的执行中,所有单个操作(例如读取和写入)都有一个与程序顺序一致的总顺序。


Each individual action is atomic and is immediately visible to every thread.

每个单独的操作都是原子的,并且对每个线程都是立即可见的。


If a program has no data races, then all executions of the program will appear to be sequentially consistent.

如果一个程序没有数据竞争,那么程序的所有执行都将看起来是顺序一致的。


As noted before, sequential consistency and/or freedom from data races still allows errors arising from groups of operations that need to be perceived atomically and are not.

如前所述,顺序一致性和/或免于数据竞争仍然允许由于以下原因引起的错误需要以原子方式感知而不是的操作组。


If we were to use sequential consistency as our memory model, many of the compiler and processor optimizations that we have discussed would be illegal.

如果我们使用顺序一致性作为我们的内存模型,我们讨论过的许多编译器和处理器优化都是非法的。


For example, in Figure 2, as soon as the write of 3 to p.x occurred, subsequent reads of that location would be required to see that value.

例如,在图 2 中,一旦将 3 写入 p.x,就需要对该位置的后续读取才能看到该值。


Having discussed sequential consistency, we can use it to provide an important clarification regarding data races and correctly synchronized programs.

在讨论了顺序一致性之后,我们可以使用它来提供有关数据竞争和正确同步程序的重要说明。


A data race occurs in an execution of a program if there are conflicting actions in that execution that are not ordered by synchronization.

如果在该执行中存在未按同步排序的冲突操作,则在该程序的执行中发生数据竞争。


A program is correctly synchronized if and only if all sequentially consistent executions are free of data races.

当且仅当所有顺序一致的执行都没有数据竞争时,程序才能正确同步。


Programmers therefore only need to reason about sequentially consistent executions to determine if their programs are correctly synchronized.

因此,程序员只需要推理顺序一致的执行来确定他们的程序是否正确同步。


A fuller treatment of memory model issues for non-final fields is given in Sections 4–6.

第 4-6 节对非最终字段的内存模型问题进行了更全面的处理。

3.2 Final Fields

Fields declared final are initialized once, but never changed under normal circumstances.

声明为 final 的字段被初始化一次,但在正常情况下永远不会改变。


The detailed semantics of final fields are somewhat different from those of normal fields.

final 字段的详细语义与普通字段有些不同。


In particular,compilers have a great deal of freedom to move reads of final fields across synchronization barriers and calls to arbitrary or unknown methods.

特别是,编译器有很大的自由来跨同步障碍移动对最终字段的读取以及对任意或未知方法的调用。


Correspondingly, compilers are allowed to keep the value of a final field cached in a register and not reload it from memory in situations where a non-final field would have to be reloaded.

相应地,允许编译器将最终字段的值缓存在寄存器中,并且在必须重新加载非最终字段的情况下不从内存中重新加载它。


Final fields also allow programmers to implement thread-safe immutable objects without synchronization.

Final 字段还允许程序员在不同步的情况下实现线程安全的不可变对象。


A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads.

线程安全的不可变对象被所有线程视为不可变的,即使使用数据竞争在线程之间传递对不可变对象的引用也是如此。


This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code.

这可以提供安全保证,防止错误或恶意代码滥用不可变类。


Final fields must be used correctly to provide a guarantee of immutability.

必须正确使用最终字段以提供不变性的保证。


An object is considered to be completely initialized when its constructor finishes.

当一个对象的构造函数完成时,它被认为是完全初始化的。


A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object’s final fields.

只有在对象完全初始化后才能看到对该对象的引用的线程可以保证看到该对象的最终字段的正确初始化值。


The usage model for final fields is a simple one. Set the final fields for an object in that object’s constructor.

final 字段的使用模型很简单。在该对象的构造函数中设置该对象的最终字段。


Do not write a reference to the object being constructed in a place where another thread can see it before the object’s constructor is finished.

在对象的构造函数完成之前,不要在另一个线程可以看到它的地方写对正在构造的对象的引用。


If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object’s final fields.

如果遵循这一点,那么当另一个线程看到该对象时,该线程将始终看到该对象最终字段的正确构造版本。


It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.

它还将看到至少与最终字段一样最新的最终字段引用的任何对象或数组的版本。

Figure 4 gives an example that demonstrates how final fields compare to normal fields.

图4给出了一个例子,展示了final字段与普通字段的比较。


The class FinalFieldExample has a final int field x and a non-final int field y.

这个类有一个final int 字段x 和一个非final int 字段 y


One thread might execute the method writer(), and another might execute the method reader().

一个线程可能执行方法 writer(),而另一个线程可能执行方法 reader()。


Because writer() writes father the object’s constructor finishes, the reader() will be guaranteed to see the properly initialized value for f.x: it will read the value 3.

因为 writer() 将对象的构造函数完成写入父亲,所以 reader() 将保证看到 f.x 的正确初始化值:它将读取值 3。


However, f.y is not final; the reader() method is therefore not guaranteed to see the value 4 for it.

然而,f.y 不是最终的;因此,不能保证 reader() 方法看到它的值 4。


Final fields are designed to allow for necessary security guarantees. 最终字段被设计为允许必要的安全保证。

Consider the code in Figure 5. 考虑图5中的代码。

String objects are intended to be immutable and string operations do not perform synchronization.


字符串对象旨在是不可变的,并且字符串操作不执行同步。

While the String implementation does not have any data races, other code could have data races involving the use of Strings, and the memory model makes weak guarantees for programs that have data races.

虽然 String 实现没有任何数据竞争,但其他代码可能存在涉及使用 String 的数据竞争,并且内存模型为具有数据竞争的程序提供了弱保证。


In particular, if the fields of the String class were not final, then it would be possible (although unlikely) that Thread 2 could initially see the default value of 0 for the offset of the string object, allowing it to compare as equal to “/tmp”.

特别是,如果 String 类的字段不是最终的,那么线程 2 有可能(尽管不太可能)最初看到字符串对象的偏移量的默认值 0,从而允许它比较等于“ /tmp”。


A later operation on the String object might see the correct offset of 4, so that the String object is perceived as being “/usr”.

稍后对 String 对象的操作可能会看到正确的偏移量 4,因此 String 对象被视为“/usr”。


Many security features of the Java programming language depend upon Strings being perceived as truly immutable, even if malicious code is using data races to pass String references between threads.

Java 编程语言的许多安全特性依赖于字符串被认为是真正不可变的,即使恶意代码正在使用数据竞争在线程之间传递字符串引用。


This is only an overview of the semantics of final fields. 这只是对final字段语义的概述

For a more detailed discussion, which includes several cases not mentioned here, consult Section 9.
如需更详细的讨论,包括此处未提及的几个案例,请参阅第 9 节。

4 What is a Memory Model?

A memory model describes, given a program and an execution trace of that program, whether
the execution trace is a legal execution of the program.

内存模型描述,给定一个程序和该程序的执行跟踪,是否执行跟踪是程序的合法执行


For the Java programming language, the memory model works by examining each read in an execution trace and checking that the write observed by that read is valid according to certain rules.

对于 Java 编程语言,内存模型的工作原理是检查执行跟踪中的每次读取,并根据特定规则检查读取观察到的写入是否有效。


The memory model describes possible behaviors of a program. 内存模型描述了程序的可能行为。


An implementation is free to produce any code it likes, as long as all resulting executions of a program produce a result that can be predicted by the memory model.

一个实现可以自由地生成它喜欢的任何代码,只要程序的所有结果执行产生的结果可以由内存模型预测。


This provides a great deal of freedom to perform a myriad of code transformations, including the reordering of actions and removal of unnecessary synchronization.

这为执行无数代码转换提供了很大的自由度,包括重新排序操作和删除不必要的同步。


A high level, informal overview of the memory model shows it to be a set of rules for when writes by one thread are visible to another thread.

内存模型的高级、非正式概述表明它是一组规则,用于当一个线程的写入对另一个线程可见时。


Informally, a read r can usually see the value of any write w such that w does not happen-after r and w is not seen to be overwritten by another write w 0 (from r’s perspective).

非正式地,读取 r 通常可以看到任何写入 w 的值,这样 w 不会在 r 之后发生,并且 w 不会被另一个写入 w 0 覆盖(从 r 的角度来看)。


When we use the term “read” in this memory model, we are only referring to actions that
read fields or array elements.

当我们在这个内存模型中使用术语“读取”时,我们仅指的是那些读取字段或数组元素。


The semantics of other operations, such as reads of array lengths, executions of checked casts, and invocations of virtual methods, are not directly affected by data races.

其他操作的语义,例如数组长度的读取、检查强制转换的执行和虚拟方法的调用,不受数据竞争的直接影响。


The JVM implementation is responsible for ensuring that a data race cannot cause incorrect behavior such as returning the wrong length for an array or having a virtual method invocation cause a segmentation fault.

JVM 实现负责确保数据竞争不会导致不正确的行为,例如返回错误的数组长度或虚拟方法调用导致分段错误。


The memory semantics determine what values can be read at every point in the program.

内存语义决定了程序中每个点可以读取哪些值。


The actions of each thread in isolation must behave as governed by the semantics of that thread, with the exception that the values seen by each read are determined by the memory model.

每个单独的线程的操作必须按照该线程的语义进行操作,但每次读取看到的值由内存模型确定。


When we refer to this, we say that the program obeys intra-thread semantics.

当我们提到这个时,我们说程序遵循线程内语义。

5 Definitions

In this section we define in more detail some of the informal concepts we have presented.

在本节中,我们更详细地定义了我们提出的一些非正式概念。


Shared variables/Heap memory: 共享变量/推内存
Memory that can be shared between threads is called shared or heap memory

在线程之间可以被共享的内存成为共享内存或堆内存。


All instance fields, static fields and array elements are stored in heap memory.

所有实例字段、静态字段和数组元素都存储在堆内存中。


We use the term variable to refer to both fields and array elements.

我们使用术语变量来指代字段和数组元素。


Variables local to a method are never shared between threads and are unaffected by the memory model.

方法的局部变量永远不会在线程之间共享,并且不受内存模型的影响。


Inter-thread Actions: 线程间操作
An inter-thread action is an action performed by one thread that can be detected or directly influenced by another thread.

线程间动作是由一个线程执行的可以被另一个线程检测或直接影响的动作。


Inter-thread actions include reads and writes of shared variables and synchronization actions, such as locking or unlocking a monitor, reading or writing a volatile variable, or starting a thread.

线程间操作包括共享变量的读取和写入以及同步操作,例如锁定或解锁监视器、读取或写入 volatile 变量或启动线程。


Also included are actions that interact with the external world (external actions), and actions that cause a thread to go into an infinite loop (thread divergence actions).

还包括与外部世界交互的动作(外部动作),以及导致线程进入无限循环的动作(线程发散动作)。


For more information on these actions, consult Section 7.1.

有关这些操作的更多信息,请参阅第 7.1 节。


We do not need to concern ourselves with intra-thread actions (e.g., adding two local variables and storing the result in a third local variable).

我们不需要关心线程内的动作(例如,添加两个局部变量并将结果存储在第三个局部变量中)。


As previously mentioned, the behavior of each thread in isolation needs to obey the correct intra-thread semantics.

如前所述,每个独立线程的行为需要遵守正确的线程内语义。


Every inter-thread action is associated with information about the execution of that action.

每个线程间动作都与该动作的执行信息相关联。


All actions are associated with the thread in which they occur and the program order in which they occur within that thread.

所有动作都与它们发生的线程以及它们在该线程中发生的程序顺序相关联。


Additional information associated with an action include: 与操作相关的附加信息包括:

  1. write The variable written to and the value written.
  2. read The variable read and the write seen (from this, we can determine the value seen).
  3. lock The monitor which is locked.
  4. unlock The monitor which is unlocked.

For brevity’s sake, we usually refer to inter-thread actions as simply actions.

为简洁起见,我们通常将线程间操作称为简单的操作。


Program Order: 程序顺序
Among all the inter-thread actions performed by each thread t, the program order of t is a total order that reflects the order in which these actions would be performed according to the intra-thread
semantics of t.

在每个线程 t 执行的所有线程间动作中,t 的程序顺序是一个总顺序,它反映了这些动作将根据线程内执行的顺序 t 的语义。


Intra-thread semantics: 线程内语义
Intra-thread semantics are the standard semantics for single threaded programs, and allow the complete prediction of the behavior of a thread based on the values seen by read actions within the thread.

线程内语义是单线程程序的标准语义,允许根据线程内读取操作看到的值来完整预测线程的行为。


To determine if the actions of thread t in an execution are legal,we simply evaluate the implementation of thread t as it would be performed in a single threaded context, as defined in the rest of the JLS.

为了确定线程t在执行中的动作是否合法,我们简单地评估线程t的实现,因为它将在单线程上下文中执行,如JLS的其余部分中所定义的。


Each time the evaluation of thread t generates an inter-thread action, it must match the interthread action a of t that comes next in program order.

每次线程t的求值产生一个线程间动作,它必须匹配程序顺序中下一个线程t的线程间动作a。


If a is a read, then further evaluation of t uses the value seen by a as determined by the memory model.

如果 a 是一个read,那么对 t 的进一步评估使用由存储器模型确定的a所看到的值。


Simply put, intra-thread semantics are what determine the execution of a thread in isolation;

简单地说,线程内语义决定了线程的独立执行;


when values are read from the heap, they are determined by the memory model.

当从堆中读取值时,它们是内存模型决定的。


Synchronization Actions:
Synchronization actions include locks, unlocks, reads of and writes to volatile variables, actions that start a thread, and actions that detect that a thread is done.

同步操作包括锁定、解锁、读取和写入 volatile 变量、启动线程的操作以及检测线程已完成的操作。


Any action that is the start or end-point of a synchronizes-with edge is a synchronization action.

任何作为 synchronizes-with 边的起点或终点的动作都是同步动作。


Such actions are listed in more detail below under happens-before edges.

此类操作在下面happens-before的边缘下更详细地列出。


Synchronization Order:
Every execution has a synchronization order. 每个执行都有一个同步顺序。


A synchronization order is a total order over all of the synchronization actions of an execution.

同步顺序是执行的所有同步操作的总顺序。


Happens-Before and Synchronizes-With Edges:

If we have two actions x and y, we use x → y to mean that x happens-before y.

如果我们有两个动作x和y,我们使用 x → y 去表示 x happens-before y。

If x and y are actions of the same thread and x comes before y in program order, then x → y.

如果x和y是同一个线程的动作,x 按程序顺序排在 y 之前,那么x → y。


Synchronization actions also induce happens-before edges.

同步动作也引起 happens-before 边


We call the resulting directed edges synchronized-with edges.

我们称得到的有向边为synchronized-with边。


They are defined as follows: 它们定义如下:

An unlock action on monitor m synchronizes-with all subsequent lock actions on m
(where subsequent is defined according to the synchronization order).

监视器 m 上的解锁操作 synchronizes-with 所有随后加锁的操作。
(随后根据同步顺序定义)

A write to a volatile variable v synchronizes-with all subsequent reads of v by any thread (where subsequent is defined according to the synchronization order).
volatile 变量v的写入 synchronizes-with 所有后续任意线程对变量 v 的读取。 (随后根据同步顺序定义)

An action that starts a thread synchronizes-with the first action in the thread it starts.
启动线程的动作与它启动的线程中的第一个动作同步。

The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated.

T2 may accomplish this by calling T1.isAlive() or doing a join action on T1.

If thread T1 interrupts thread T2, the interrupt by T1 synchronizes-with any point where any other thread (including T2) determines that T2 has been interrupted.

This can be done by having an InterruptedException thrown or by invoking Thread.interrupted or
Thread.isInterrupted.

  • The write of the default value (zero, false or null) to each variable synchronizes-with to the
    first action in every thread.Although it may seem a little strange to write a default value to a variable before the object containing the variable is allocated, conceptually every object is created at the start of the
    program with its default initialized values. Consequently, the default initialization of any
    object happens-before any other actions (other than default writes) of a program. 向每个变量写入默认值(零、假或空)与同步 每个线程的第一个动作。虽然在分配包含变量的对象之前向变量写入默认值看起来有点奇怪,但从概念上讲,每个对象都是在 程序使用其默认的初始化值。因此,任何 对象发生-在程序的任何其他动作(除了默认写入)之前。

  • At the invocation of a finalizer for an object, there is an implicit read of a reference to that
    object. There is a happens-before edge from the end of a constructor of an object to that
    read. Note that all freezes for this object (see Section 9.2) happen-before the starting point
    of this happens-before edge . 在调用对象的终结器时,会隐式读取对该对象的引用 对象。从一个对象的构造函数的末尾到该对象的构造函数的末尾有一个发生前边缘 阅读。请注意,该对象的所有冻结(参见第9.2节)都发生在起点之前 这发生在边缘之前。

If an action x synchronizes-with a following action y, then we also have x → y.
如果一个动作x与后面的动作y同步,那么我们也有x → y。

Further more,happens-before is transitively closed. In other words, if x → y and y → z, then x → z.
此外,发生之前是传递封闭的。换句话说,如果x → y,y → z,那么x → z。

It should be noted that the presence of a happens-before relationship between two actions does
not necessarily imply that they have to take place in that order in an implementation. 应该注意的是,两个动作之间发生之前关系的存在 不一定意味着它们必须在实现中以该顺序发生。

If the reordering produces results consistent with a legal execution, it is not illegal. 如果重新排序产生与合法执行一致的结果,则不违法。

For example, the write of a default value to every field of an object constructed by a thread need not happen before the beginning of that thread, as long as no read ever observes that fact. 例如,向由线程构造的对象的每个字段写入默认值不需要发生在该线程开始之前,只要没有读取观察到该事实。

More specifically, if two actions share a happens-before relationship, they do not necessarily have
to appear to have happened in that order to any code with which they do not share a happensbefore relationship. 具体地说,如果两个动作共享一个发生之前关系,它们不一定有 看起来是以这种顺序发生在任何代码上的,而这些代码并不与它们共享发生之前的关系。

Writes in one thread that are in a data race with reads in another thread may,for example, appear to occur out of order to those reads. 例如,一个线程中的写操作与另一个线程中的读操作发生数据竞争时,这些读操作可能会出现乱序。

The wait methods of class Object have lock and unlock actions associated with them; their happens-before relationships are defined by these associated actions. 类对象的等待方法具有与其相关联的锁定和解锁动作;它们的发生前关系由这些关联的动作定义。

These methods are described further in Section 14. 这些方法将在第14节中进一步描述。

6 Approximations to a Java Memory Model

In Section 3.1, we described sequential consistency. 在3.1节中,我们描述了顺序一致性。

It is too strict for use as the Java memory model,because it forbids standard compiler and processor optimizations. 对于用作Java内存模型来说,它太严格了,因为它禁止标准的编译器和处理器优化。

This section reviews sequential consistency, and presents another model, called the happens-before memory model. 本节回顾顺序一致性,并提出另一个模型,称为发生在内存模型之前。

This model is closer to fulfilling the needs of the Java memory model, but it is too weak; it allows unacceptable violations of causality. 这个模型更接近于满足Java内存模型的需求,但是它太弱了;它允许不可接受的违反因果关系。

The problems with causality are described in Section 6.3. 第6.3节描述了因果关系的问题。

In Section 7, we present the Java memory model, a formal model that strengthens the happensbefore memory model to provide adequate guarantees of causality. 在第7节中,我们介绍了Java内存模型,这是一个正式的模型,它加强了内存模型之前的事件,以提供充分的因果保证。

6.1 Sequential Consistency Memory Model

Formally, in sequential consistency, all actions occur in a total order (the execution order) that is
consistent with program order; furthermore, each read r of a variable v sees the value written by
the write w to v such that: 从形式上讲,在顺序一致性中,所有的动作都以一个总的顺序(执行顺序)发生,即 与节目顺序一致;此外,变量v的每次读取r都会看到由 w到v的写法如下:

6.2 Happens-Before Memory Model

Before presenting the Java memory model in full, we will present a simpler memory model, called the happens-before memory model. 在完整介绍Java内存模型之前,我们将介绍一个更简单的内存模型,称为发生前内存模型。

This model involves several properties/requirements: 该模型涉及几个属性/要求:

  • There is a total order over all synchronization actions, known as the synchronization order. 所有同步操作都有一个总的顺序,称为同步顺序。
  • This order is consistent with program order and with mutual exclusion of locks. 这个顺序与程序顺序一致,并且锁是互斥的。
  • Synchronization actions induce synchronizes-with edges between matched actions, as described in Section 5. 同步动作导致匹配动作之间的边同步,如第5节所述。
  • The transitive closure of the synchronizes-with edges and program order gives a partial order
    known as the happens-before order, as described in Section 5. 边同步和程序序的传递闭包给出了一个偏序 称为发生前顺序,如第5节所述。
  • The values that can be seen by a non-volatile read are determined by a rule known as happensbefore consistency. 非易失性读取可以看到的值是由一致性之前发生的规则确定的。
  • The value seen by a volatile read are determined by a rule known as synchronization order
    consistency. 易失性读取器看到值由称为同步顺序的规则确定 一致性。

Happens-before consistency says that a read r of a variable v is allowed to observe a write w to v if, in the happens-before partial order of the execution trace: 发生前一致性表示,如果在执行跟踪的发生前部分顺序中:

  • r is not ordered before w (i.e., it is not the case that r → w), and
  • there is no intervening write w to v (i.e., no write w to v such that w → w hb → r).

Synchronization order consistency says that each read r of a volatile variable v returns the last
write to v to come before it in the synchronization order. 同步顺序一致性表示对可变变量v的每次读取r都返回最后一次 写入v,使其在同步顺序中位于v之前。

For example, the behavior shown in Figure 1 is allowed by the happens-before memory model. 例如,图1所示的行为是发生在内存模型之前所允许的。

There are no synchronizes-with or happens-before edges between threads, and each read is allowed
to see the write by the other thread. 线程之间没有同步或先发制人的边,每次读取都是允许的 查看另一个线程的写操作。

6.3 Causality

The happens-before memory model represents a necessary, but not sufficient, set of constraints. 发生之前的记忆模型代表了一个必要的,但不是充分的约束集。

All behaviors allowed by the Java memory model are also allowed by the Happens-before memory
model, but the happens-before memory model allows unacceptable behaviors – those that violate
the requirements we have established. Java内存模型允许的所有行为也是发生前内存所允许的 模型,但是发生在记忆模型允许不可接受的行为——那些违反 我们已经确定的要求。

These can all be viewed as violations of causality in an unacceptable way. 这些都可以被视为以不可接受的方式违反了因果关系。

In this section, we talk about some of the ways in which the Happens-before model is unsatisfactory, and ways in which it can be tweaked to provide the necessary guarantees. 在这一节中,我们将讨论发生之前模型不令人满意的一些方面,以及可以对其进行调整以提供必要保证的方法。

6.3.1 Happens-Before is too Weak

The most significant weakness for the Happens-before model is that it allows values to appear “out
of thin air”. “发生之前”模型最大的缺点是它允许值出现在“外面” 无中生有”。

This can be seen by a detailed examination of Figure 6. 这可以通过对图6的详细研究看出。

The code shown in Figure 6 is correctly synchronized. 图6所示的代码是正确同步的。

This may seem surprising, since it doesn’t perform any synchronization actions. 这似乎令人惊讶,因为它不执行任何同步操作。

Remember, however, that a program is correctly synchronized if, when it is executed in a sequentially consistent manner, there are no data races. 但是,请记住,如果以顺序一致的方式执行程序时,没有数据竞争,则程序是正确同步的。

If this code is executed in a sequentially consistent way, each action will occur in program order, and neither of the writes will occur. 如果以顺序一致的方式执行此代码,每个操作都将按程序顺序发生,而两个写操作都不会发生。

Since no writes occur, there can be no data races: the program is correctly synchronized. 因为没有写操作发生,所以不会有数据竞争:程序是正确同步的。

Since this program is correctly synchronized, the only behaviors we can allow are sequentially consistent behaviors (by “sequentially consistent behaviors”, we mean any behavior that appears externally to have the same results as a sequentially consistent execution). 因为这个程序是正确同步的,所以我们唯一允许的行为是顺序一致的行为(所谓“顺序一致的行为”,我们指的是任何从外部看起来与顺序一致的执行具有相同结果的行为)。

However, there is an execution of this program that under the happens-before memory model in which r1 == r2 == 1. 然而,在r1 == r2 == 1的发生前记忆模型下,有一个程序的执行。

Just as before, since there are no synchronizes-with or happens-before edges, each read is allowed
to see the write by the other thread. 和以前一样,因为没有同步或发生在边沿之前,所以每次读取都是允许的 查看另一个线程的写操作。

We refer to the issue of when a write can seem to occur before a read that it depends on as
causality, because it involves the question of whether a write is causing itself to occur. 我们将写操作何时看似发生在它所依赖的读操作之前的问题称为 因果关系,因为它涉及到写操作是否导致自身发生的问题。

In Figure 6. the reads cause the writes to occur, and the writes cause the reads see the values that they see.
在图6中。读操作导致写操作发生,而写操作导致读操作看到它们看到的值。

There is no “first cause” for the actions. 行动没有“第一原因”。

Our memory model therefore needs an acceptable and consistent way of determining which such apparent causal loops are allowed. 因此,我们的记忆模型需要一种可接受且一致的方式来确定哪些明显的因果循环是允许的。

Even when a program is incorrectly synchronized, there are certain behaviors that violate causality in a way that is considered unacceptable. 即使当一个程序不正确地同步时,也有某些行为以一种被认为不可接受的方式违反了因果关系。

An example of this is given in Figure 7;the behavior r1 == r2 == 42 is allowed by the happens-before memory model, but unacceptable.
图7给出了一个例子;行为r1 == r2 == 42是之前发生的记忆模型所允许的,但却是不可接受的。

6.3.2 Causality is Subtle

The notion of causality is not a simple one, as it is not simple to determine which actions cause
others to occur. 因果关系的概念并不简单,因为要确定哪些行为导致了什么并不简单 其他发生。

The Java memory model allows the behavior shown in Figure 8, even though that
example also seems to involve a case of circular causality. Java内存模型允许图8所示的行为,尽管 例子似乎也涉及到循环因果关系的情况。

This behavior must be allowed, because a compiler can 必须允许这种行为,因为编译器可以

eliminate the redundant read of a, replacing r2 = a with r2 = r1, then determine that the expression r1 = r2 is always true, eliminating the conditional branch 3,and finally move the write 4: b = 2 early.
消除a的冗余读,用r2 = r1代替r2 = a,然后确定表达式r1 == r2永远为真,消除条件分支3,最后提前移动写4: b = 2。


After the compiler does the redundant read elimination, the assignment 4: b = 2 is guaranteed to happen; the second read of a will always return the same value as the first.
编译器做了冗余读消除后,赋值4: b = 2保证发生;对的第二次读取将始终返回与第一次相同的值。

Thus, simple compiler optimizations can lead to an apparent causal loop.
因此,简单的编译器优化会导致明显的因果循环。

There must therefore be no causal relationship between the reads of a and the write to b, even though a cursory examination of the code might indicate that one exists. 因此,对a的读取和对b的写入之间必须没有因果关系,即使粗略地检查代码可能会发现存在因果关系。

Note that intra-thread semantics and out-of-thin-air safety guarantee that if r1 6= r2, then Thread 1 will not write to b, and r3 = 1 . 注意,线程内语义和无中生有的安全性保证,如果r1 6= r2,那么线程1不会写入b,r3 = 1。

Figure 9 shows another example in which the compiler should be allowed to perform a global
analysis that eliminates a relationship that appears at first glance to be causal.
图9显示了另一个例子,在这个例子中编译器应该被允许执行一个全局的 排除乍一看似乎是因果关系的分析。

In order for r1 == r2 == r3 == 1, Thread 1 would seemingly need to write 1 to y before reading x.
为了让r1 == r2 == r3 == 1,线程1似乎需要在读取x之前将1写入y

However, a compiler could use an interthread analysis to determine that the only possible values for x and y
are 0 or 1. 但是,编译器可以使用线程间分析来确定x和y的唯一可能值 为0或1。

Knowing this, the compiler can determine that r2 is always 1. 知道了这一点,编译器就可以确定r2总是1。

Thus, the write of 1 to y is not affected by the read of x and the write can be performed early.
因此,从1到y的写入不受对x的读取的影响,并且可以较早地执行写入。

6.3.3 An Approach to Causality

The Java memory model takes as input a given execution, and a program, and determines whether
that execution is a legal execution of the program. Java内存模型将给定的执行和程序作为输入,并确定是否 该执行是程序的合法执行。

It does this by gradually building a set of “committed” actions that reflect which actions we know can be executed by the program without requiring a “causal loop”. 它通过逐步构建一组“提交的”动作来做到这一点,这些动作反映了我们知道哪些动作可以由程序执行,而不需要“因果循环”。

Usually, the next action to be committed will reflect the next action that can be performed by a sequentially consistent execution. 通常,要提交的下一个动作将反映顺序一致的执行可以执行的下一个动作。

However, to reflect reads that see later in the program order of other threads writes, we allow some actions to be committed earlier than other actions that happen-before them. 然而,为了反映在其他线程写的程序顺序中看到较晚的读,我们允许一些动作比发生在它们之前的其他动作更早提交。

Obviously, some actions may be committed early and some may not. 显然,有些行为可能会提前实施,有些则不会。

If, for example, one of the writes in Figure 6 were committed before the read of that variable, the read could see the write, and the “out-of-thin-air” result could occur. 例如,如果在读取该变量之前提交了图6中的一个写操作,则读取操作可以看到该写操作,并且可能会出现“无中生有”的结果。

Informally, we allow an action to be committed early if we know that the action can occur without assuming some data race occurs. 非正式地,如果我们知道一个动作可以发生而不需要假设一些数据竞争发生,我们允许这个动作被提前提交。

In Figure 6, we cannot perform either write early, because the writes cannot occur unless the reads see the result of a data race. 在图6中,我们不能提前执行任何一个写操作,因为除非读操作看到数据竞争的结果,否则写操作不会发生。

In Figure 8, on the other hand, we know that the write to b can happen regardless of whether a data race occurs. 另一方面,在图8中,我们知道无论是否发生数据竞争,对b的写入都会发生。

7 Formal Specification of the Java Memory Model

Java内存模型的形式规范

This section provides the formal specification of the Java memory model (excluding final fields, which are described in Section 9).

本节提供了Java内存模型的正式规范(不包括final字段,这将在第9节中描述)。

7.1 Actions and Executions 行动和执行


一个动作 a 被元组 t k v u 描述,包括 t - 执行动作的线程,k - 动作的种类:可见读 。。。,v - 动作涉及的变量和监视器。 u - 动作的任一标识符。

一个执行E由一个元组描述,包含


p - 一个程序,a - 一系列动作, po - 程序顺序,对于每个线程 t,是 t 在 a 中执行的所有动作的总顺序,so -同步顺序,即A中所有同步动作的总顺序,W - 一个 write-seen 函数,对于 A 中的每次读取 r,它给出 W®,即 r 在 E,V - 一个函数, sw - synchronizes-with,同步操作的部分顺序,hb - happens-befor,动作的部分顺序。

请注意,synchronizes-with 和happens-before 是由另一个唯一确定的执行的组成部分和格式良好的执行规则

Two of the action types require special descriptions, and are detailed further in Section 7.5.
其中两种动作类型需要特殊描述,并在第 7.5 节中进一步详述。

These actions are introduced so that we can explain why such a thread may cause all other threads to stall and fail to make progress. 引入这些动作是为了解释为什么这样一个线程可能会导致所有其他线程停滞不前,无法取得进展。

external actions - An external action is an action that may be observable outside of an execution, and may have a result based on an environment external to the execution. 外部动作 - 外部动作是可以在执行之外观察到的动作,并且可以具有基于执行之外的环境的结果。

An external action tuple contains an additional component, which contains the results of the external action as
perceived by the thread performing the action. 外部动作元组包含附加组件,该组件包含外部动作的结果,如 由执行该动作的线程感知。

This may be information as to the success or failure of the action, and any values read by the action.
这可以是关于动作成功或失败的信息,以及动作读取的任何值。

Parameters to the external action (e.g., which bytes are written to which socket) are not part of the external action tuple. 外部动作的参数(例如,哪些字节被写入哪个套接字)不是外部动作元组的一部分。

These parameters are set up by other actions within the thread and can be determined by examining the intra-thread semantics. 这些参数由线程内的其他动作设置,并且可以通过检查线程内语义来确定。

They are not explicitly discussed in the memory model. 在内存模型中没有明确讨论它们。

In non-terminating executions, not all external actions are observable.
在非终止执行中,并不是所有的外部动作都是可见的。

Non-terminating executions and observable actions are discussed in Section 7.5.
第7.5节讨论了非终止执行和可观察动作。

thread divergence action - A thread divergence action is only performed by a thread that is in
an infinite loop in which no memory, synchronization or external actions are performed.
线程分流操作——线程分流操作只能由 一个无限循环,其中不执行任何内存、同步或外部操作。

If a thread performs a thread divergence action, that action is followed in program order by an
infinite sequence of additional thread divergence actions. 如果一个线程执行一个线程分歧操作,则该操作之后的程序顺序是 额外线程分歧动作的无限序列。

7.2 Definitions

Definition of synchronizes-with. Section 5 defines synchronizes-with edges.

The source of a synchronizes-with edge is called a release, and the destination is called an acquire.

Definition of happens-before.

The happens-before order is given by the transitive closure of the synchronizes-with and program order orders.

This is discussed in detail in Section 5.

Definition of sufficient synchronization edges.

A set of synchronization edges is sufficient if it is the minimal set such that you can take the transitive closure of those edges with program order edges, and determine all of the happens-before edges in the execution.

This set is unique.

JSR-133: JavaTM Memory Model and Thread Specification原文解析相关推荐

  1. JSR 133 Java内存模型以及并发编程的最权威论文汇总

    Java内存模型 先看官方文档: https://docs.oracle.com/javase/specs/ JSR 133:Java TM内存模型和线程规范修订版:https://www.jcp.o ...

  2. Java内存模型(Java Memory Model,JMM)

    导读 本文通过对JSR133规范的解读,详细的介绍JMM的核心理论,并将开发中常用的关键字的实现原来做了详细的介绍.通过本文读者可以了解到并发的一些基本理论,并对一些同步原语有了更深层次的理解.希望读 ...

  3. Java (JVM) Memory Model – Memory Management in Java

    原文地址:http://www.journaldev.com/2856/java-jvm-memory-model-memory-management-in-java Understanding JV ...

  4. Java (JVM) Memory Model and Garbage Collection Monitoring Tuning

    java内存模型以及GC(垃圾回收监视器)调优 原文:http://www.journaldev.com/2856/java-jvm-memory-model-and-garbage-collecti ...

  5. 内存模型-Memory Model

    文章目录 1.1 CPU Cache 的产生背景 1.2 CPU Cache 模型 1.3 什么是 Cache Line 1.4 Flase Sharing 问题 1.5 CPU 缓存一致性协议 1. ...

  6. JMM~Java Memory Model

    JMM概念 [JMM](Java Memory Model的缩写)允许编译器和缓存以数据在处理器特定的缓存(或寄存器)和主存之间移动的次序拥有重要的特权,除非程序员使用了volatile或synchr ...

  7. p8大佬告诉你JSR - 133 都解决了哪些问题?

    究竟什么是内存模型? 在多处理系统中,每个 CPU 通常都包含一层或者多层内存缓存,这样设计的原因是为了加快数据访问速度(因为数据会更靠近处理器) 并且能够减少共享内存总线上的流量(因为可以满足许多内 ...

  8. JAVA 内存模型 (Java Memory Model,JMM)

    JAVA内存模型 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. Java内存模型(Java Memory Model,JMM) 是在硬件内存模型基 ...

  9. [zz from newsmth] 王大牛的Memory Model reading list

    发信人: yifanw (王轶凡), 信区: CPlusPlus 标  题: 内存模型之参考文献 发信站: 水木社区 (Sun Mar 15 22:51:46 2009), 站内 前两篇文章,希望大家 ...

最新文章

  1. 访中科曙光智能计算技术总监许涛:重新认识面向未来的AI服务器和云计算中心...
  2. Redis SLAVE过期键策略
  3. 微信企业号:shell定时发送图片 到 指定人
  4. Android复习11【service-音乐播放器、定时器、IntentService、ALDL使用】
  5. go语言json字符串解析为结构体数组,结构体指针的数组
  6. script的defer和async
  7. OpenTelemetry - 云原生下可观测性的新标准
  8. 模版:线段树合并+线段树分裂
  9. Windows 系统下.sh文件的运行
  10. MVVM架构~knockoutjs系列之验证信息自定义输出~再续
  11. mysql 360 atlas_360 Atlas中间件安装及使用
  12. centos怎么装python_centos下安装python的过程
  13. Nginx+Keepalived主备配置
  14. 还在痴迷于大数据?未来 “小数据” 会让你大开眼界
  15. 说说你对AQS的理解?
  16. 最简真分数c语言,HihoCoder1655 : 第K小最简真分数([Offer收割]编程练习赛39)(唯一分解+容斥定理+二分)(不错的数学题)...
  17. 项目管理 :PMO三种角色
  18. C语言运算符的优先级和结合性
  19. Windows Server 2008 安装教程——图文小白版(附下载地址)
  20. java课前演讲讲什么_课前演讲讲什么比较有创意(逼格)?

热门文章

  1. Sniffer报文放送
  2. 如何成为有效学习的高手 学习笔记
  3. u盘怎么进入pe系统并修改系统密码
  4. 在微信小程序中如何下载APP?
  5. uni-app新闻小程序
  6. WSL无法打开或者卡死
  7. Pr:创建和使用收录预设
  8. WIN10隐藏任务栏和桌面图标(简易实现)
  9. Dongxiexidu
  10. python概率密度函数参数估计_Python与项目反应理论:基于EM和MCMC的参数估计算法...