Java Theory and Practice: Repairing the Java memory model, part 1th

Source: Internet
Author: User
Tags final volatile

A JSR 133, which has been active for nearly three years, recently released a public recommendation on how to fix the Java memory model (Java Memory models, JMM). There are several serious flaws in the original JMM, which leads to some incredibly difficult conceptual semantics that were originally considered simple, such as volatile, final, and synchronized. In this period of Java theory and practice, Brian Goetz shows how to strengthen the semantics of volatile and final to fix JMM. Some of these changes have been integrated into JDK 1.4, while others will be included in JDK 1.5.

The Java platform integrates threading and multi-processing technology into the language, which is much more integrated than most of the previous programming languages. The language's support for platform-independent concurrency and multi-threaded technology is ambitious and groundbreaking, and perhaps not surprisingly, this problem is a little more difficult than the original idea of the Java architecture designer. Many of the low-level obfuscation about synchronization and thread safety are subtle nuances of the Java Memory Model (JMM), which were originally specified in chapter 17th of the Java Language specification and were redefined by JSR 133.

For example, not all multiprocessor systems show cache consistency (cached coherency); If a processor has an updated variable whose value is in its cache but has not been stored in main memory, the other processor may not be able to see the updated value. In the case of a cache lack of consistency, two different processors can see that there are two different values in the same location in memory. This may sound unlikely, but it's intentional--it's a way to achieve higher performance and scalability--but it adds to the burden of developers and compilers writing code to solve these problems.

What is the memory model, and why do I need a memory model?

The memory model describes the relationship between variables in the program (instance domain, static domain, and array elements), as well as low-level details such as storing variables in the actual computer system in memory and fetching variables from memory. The object is eventually stored in memory, but the compiler, runtime, processor, or cache can be privileged to save or retrieve the value of the variable at the specified memory location of the variable at timed intervals. For example, to optimize a circular index variable, the compiler may choose to store it in a register, or the cache will be deferred to a more appropriate time before a new variable value is stored in main memory. All of these optimizations are designed to help achieve higher performance, which is usually transparent to the user, but for a multiple-processing system, these complex things can sometimes be completely apparent.

JMM allows compilers and caches to have important privileges in the order in which data is moved between processor-specific caches (or registers) and main memory, unless the programmer has explicitly requested some visibility guarantees using synchronized or final. This means that, in the absence of synchronization, the operation of the memory takes place in a different order from a different thread point of view.

Correspondingly, languages like C and C + + do not have a memory model to display--but the C language program inherits the memory model of the executing program's processor (although a compiler for a given architecture might know something about the memory model of the underlying processor, and part of the responsibility for consistency falls to the compiler's head. ON). This means that concurrent C-language programs can run correctly in one, but not on another, processor architecture. While JMM may be a bit confusing at first, there's a big benefit-a program that is properly synchronized according to JMM can run correctly on any Java-enabled platform.

The shortcomings of the original JMM

Although the JMM specified in chapter 17th of the Java Language specification is an ambitious attempt to define a consistent, cross-platform memory model, it has some subtle and important drawbacks. The semantics of synchronized and volatile are so confusing that many insightful developers sometimes choose to ignore them because it is difficult to write code that is properly synchronized under the old storage model.

The old JMM allows strange and confusing things to happen, such as the final field does not seem to have the same value set in the constructor (so that the imaginary immutable object is not immutable) and the unexpected result of a reordering of the memory operations. This also prevents some other valid compiler optimizations. If you read any article about double check locking (double-checked locking problem) (see Resources), you'll remember how confusing memory operations are, and when you're not synchronizing properly (or trying to avoid synchronization actively), How subtle but serious problems can be hidden in your code. Worse, many programs that do not synchronize correctly seem to work well in some cases, such as under a slight load, on a single-processor system, or on a processor with a stronger memory model than the JMM requires.

The term "reorder" is used to describe several types of true and distinct reordering of memory operations:

When the compiler does not change the semantics of the program, it can optionally reorder certain instructions as an optimization.

In some cases, you can allow the processor to perform some operations in reverse order.

The cache is usually allowed to store variables in main memory in the same order that the program writes the variable.

From the point of view of another thread, any of these conditions can cause actions to occur in a different order than the sequence specified by the program--and ignore the reordered source code, which the memory model considers to be equal.

The goal of JSR 133

JSR 133 is mandated to fix JMM, and it has several goals:

Retain existing security assurances, including type safety.

Provides a fictitious security (Out-of-thin-air safety). This means that the value of the variable is not created "out of nothing"-so for a thread to observe that a variable has a variable value x, a thread must have actually written the variable value x to that variable before.

The semantics of the "properly synchronized" program should be as simple and intuitive as possible. In this way, "properly synchronized" should be formally and intuitively defined (the two definitions should be consistent).

Programmers should have the confidence to create multithreaded programs. Of course, we don't have the magic to make it easy to write concurrent programs, but our goal is to ease the burden of programmers understanding all the details of the memory model.

High-performance JVM implementations across a wide range of popular hardware architectures should be possible. Modern processors are very different in their memory models; JMM should be able to fit the actual architecture as much as possible without sacrificing performance.

Provides a synchronous idiom (idiom) to allow us to publish an object and make it visible without synchronizing. This is a new security guarantee called initialization security (initialization safety).

There should be minimal impact on existing code.

It is noteworthy that vulnerable technologies (such as double check locking) still have vulnerabilities under the new memory model, and that the "fix" double check locking technique is not a goal for the new memory model. (However, the new semantics of volatile allow one of the commonly proposed optional methods of dual-check locking to work correctly, although we do not encourage this technique.) )

In the three years since the JSR process became active, it has been found that these problems are much more subtle than any that they deem important. This is the price of being a pioneer! The final formal semantics are much more complex than originally expected, and in fact it takes a completely different form than originally thought, but the informal semantics are clear and intuitive and are outlined in the 2nd part of this article.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.