1. Happen Before Operation:
1) Each action in a thread happens before every action in that thread that comes later in the program's order.
2) An unlock on a monitor happens before every subsequent lock on that same monitor.
3) A write to a volatile field happens before every subsequent read of the same volatile field.
4) A call to start() on a thread happens before any actions in the started thread.
5) All actions in a thread happen before any other thread successfully returns from a join() on that thread.
Another implication is that the following pattern, which some people use to force a memory barrier, doesn't work:
synchronized(new Object){ // some operations you do not want to be reordered }
This is actually a no-op, and your compiler can remove entirely. because the compiler knows that no other thread will synchronize on the same monitor.
2. How can final fields appear to change their values?
1) String.substring()
3. What do volatile do?
1) Volatile variables cannot be reordered with each other, and it is now no longer easy to reorder normal field accesses around them.
2) Anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
class VolatileExample { int x = 0; volatile boolean v = false; public void writer() { x = 42; v = true; } public void reader() { if (v == true) { //uses x - guaranteed to see 42. } } }
Assume that one thread is calling writer(), and another thread is calling reader(). The write to v in writer releases the write to x in memory, and the read of v acquires that value from main memory.
Thus if reader sees the value true for v, it is also guarenteed to see the write to 42 that happened before it. This would not have been true under the old memory model.
If v were not volatile, then the compiler could reorder the writes in writer, and reader's read of x might see 0.
4. What is double-checked locking(DCL)?
The infamous double-checked locking idiom (also called the multithreaded singleton pattern) is a trick to designed to support lazy initialization while avoiding the overhead of synchronization.
1> Traditional un-thread safe lazy initialization:
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (null == instance) { instance = new Singleton(); } return instance; } }
There may be an occasion that between line 8 and line 9, when thread A enters line 8, and before it has the chance to call line 9, thread B enters line8, then both thread A and thread B will call line 9.
This could create two different instances.
2> Use synchronized, but this cost is pretty high, because when we construct the instance we need synchronize, but after that, we do not need synchronize anymore.
public class Singleton { private static Singleton instance; private Singleton() { } public synchronized static Singleton getInstance() { if (null == instance) { instance = new Singleton(); } return instance; } }
3> Here comes double-checked locking(DCL):
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (null == instance) { synchronized (instance) { if (null == instance) { instance = new Singleton(); } } } return instance; } }
When both thread A and thread B enters line8, and they will enter the synchronized(instance) block sequentially, the first thread enters this block will create this instance, and the other will not.
And this guaranteed synchronization when create instance, and removed synchronization after instance is created.
But this approach is "smart, but broken"*(2). As the JMM enabled reordering as long as they follow the "happen before" rules.
The normal sequence of construct a object is: 1> Allocate memory space for instance 2> Call constructor for instance 3>Return reference to instance. There could be a chance that operation sequence reordered to: 1>, 3>, 2>. When thread A is executed 1>, 3>, then thread B comes to line 8, and it will get the unfully initialized object instance. There might be another case that because of memory cache, thread B comes to line 8, and returns a stale instance because it never have the chance to go to synchronize(instance) and fetch the updated instance.
4. Does the new memory fix the "Double-Checked Locking" problem?
Many people assumed that the use of volatile keyword would eliminate the problems that arises when trying to use the double-checked locking pattern.
In JVM prior to 1.5, volatile would not ensure that it worked because of instruction reordering.
Under the new memory model, making the instance field volatile would fix the problem. because there will be a happen before relationship between initializaiton of the instance by the constructing thread(thread A), and the return thread (thread B) that reads it.
Reference Links:
1) http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html
2) http://f.dataguru.cn/thread-286994-1-1.html
3) http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
相关推荐
This book covers: Basic concepts of concurrency and thread safety Techniques for building and composing ...Advanced topics such as atomic variables, nonblocking algorithms, and the Java Memory Model
This book covers:, Basic concepts of concurrency and thread safety, Techniques ... Testing concurrent programs, Advanced topics such as atomic variables, nonblocking algorithms, and the Java Memory Model
This book covers:, Basic concepts of concurrency and thread safety, Techniques ... Testing concurrent programs, Advanced topics such as atomic variables, nonblocking algorithms, and the Java Memory Model
- **JMM(Java Memory Model)**:定义了线程之间如何共享和通信数据。 - **happens-before原则**:保证了线程间的有序性和可见性。 通过阅读《Java并发编程实践》,开发者能够掌握Java并发编程的核心概念、工具...
除了讲述基础概念和同步机制,本书还着重介绍了Java内存模型(Java Memory Model),这是理解Java并发编程的关键部分,涉及到变量可见性、原子性、有序性等内存操作的行为。Java内存模型为程序员提供了清晰的并发...
1. **Java Memory Model(Java内存模型)** 2. **Monitor(监视器)** 3. **Atomic Field Assignment(原子字段赋值)** 4. **Thread(线程)** 5. **synchronized关键字** 6. **volatile关键字** 7. **Locks(锁)*...
Java内存模型(Java Memory Model, JMM)定义了在多线程环境中,Java程序中的变量(字段、数组元素)如何被线程安全地读取和修改。JMM的关键在于它规定了一组规则,这些规则确保了不同线程之间的数据一致性。具体来...
13. **内存模型和并发(Memory Model and Concurrency)**:JDK 1.5.0改进了内存模型,强化了并发编程的支持,例如添加了`java.util.concurrent`包,包含了线程池、并发集合等高效并发工具。 综上所述,Java JDK ...
- **Java Memory Model (JMM)**: Detailed explanation of the JMM, including its rules and the concept of "Happens-Before" to ensure correct concurrent behavior. - **Locks and Conditions**: Overview of...
3. **JVM 内存模型**(Java Memory Model, JMM): 描述了线程如何访问和修改共享变量,确保多线程环境下的正确性和一致性。Java 1.6 对 volatile 变量的处理和内存屏障进行了优化,提高了并发性能。 4. **异常处理*...
《Programming Concurrency on the JVM》这本书针对Java虚拟机(JVM)平台上的并发编程进行了深入探讨,为开发者提供了一系列实用的指导和示例。本文将根据该书的部分内容和读者反馈,总结出几个关键的知识点,帮助...
Java内存模型(JMM,Java Memory Model)定义了线程如何访问和修改共享变量,以及这些操作如何在不同的线程之间可见。JMM保证了线程间的同步和一致性,例如通过volatile关键字保证变量的可见性,通过synchronized...
##### 2.1 Java内存模型(Java Memory Model, JMM) Java内存模型定义了Java虚拟机(JVM)实现必须为Java程序员提供的保证,特别是在编写并发代码时。该模型规定了读取字段、写入字段以及同步监视器等操作的行为,...
- S-33可能涵盖JVM内存模型(JVM Memory Model),理解堆、栈、方法区等对优化代码有很大帮助。 - S-34可能介绍异常分类,如检查异常(Checked Exceptions)和运行时异常(Unchecked Exceptions)的区别。 - S-35...
Concurrency on the JVM and the Java Memory Model Chapter 3. Traditional Building Blocks of Concurrency Chapter 4. Asynchronous Programming with Futures and Promises Chapter 5. Data-Parallel ...
Java通过一系列关键字、内存模型(JMM,Java Memory Model)和Happens-Before规则来解决并发问题。比如,`synchronized`关键字用于同步控制,它可以作用于方法和代码块,确保同一时间只有一个线程执行。`volatile`...
1. **内存模型 (Memory Model)** - 内存模型是并发编程的基础之一,它定义了多线程环境下变量可见性、有序性和原子性的规则。 - Java内存模型确保了不同线程之间数据的一致性访问,通过`synchronized`关键字、`...
- **Memory Structures**: 内存结构,如共享池、缓冲区缓存等。 ### 12. SmartClient Ajax框架架构图 SmartClient是一种基于Ajax的RIA(Rich Internet Application)框架,用于构建高性能的Web应用。SmartClient...
JMM(Java Memory Model)是 Java 中的一种内存模型,描述了 Java 中的内存管理机制。JMM 提供了多种内存管理机制,例如原子变量、volatile 变量等。 volatile volatile 是 Java 中的一种关键字,用于描述共享变量...