JMM:java存储模型
1、java语言规定jvm要维护内部线程类似顺序化语意:
程序的执行的最终结果要等同于它在严格的顺序化环境中的执行结果.
2、JMM规定jvm的一种最小保证:什么时候写入一个变量的值对其它线程可见.
3、重排序(在编译时、运行时、硬件进行存储操作时都有可能发生重排序).
4、java存储模型定义了一些行为,所谓行为包括:变量的读写,监视器的加锁和释放锁、线程的启动和join.
5、JMM为所有内部的行为定义了一个偏序关系,即:happens-before.
Happens-before法则:(保证数据的内存可见性,即如果A happens-before B,那么A对内存的操作都可以被B看见)
1、程序次序法则:线程中的每个动作A都happen-before于该线程中的每一个动作B,其中,在程序中,所有的动作B都出现在动作A之后.
2、监视器锁法则:对一个监视器锁的解锁操作都happen-before于每一个后续对同一监视器锁的加锁操作.
3、volatile变量法则:对volatile域的写入操作happens-before于每一个后续对同一域的读操作.
4、线程启动法则:在一个线程中,对Thread.start的调用操作happens-before于每一个启动线程中的动作.
5、线程终结法则:线程中的任何动作都happens-before于其它线程检测到这个线程已经终结、或者从Thread.join调用中成功返回、 或者Thread.isAlive返回false.
6、中断法则:一个线程调用另一个线程interrupt happens-before 于被中断的线程发现中断(通过抛出InterruptedException,或者调用isInterrupted 和 interrupted).
7、一个对象的构造函数的结束 happens-before 于这个对象 finalizer 的开始.
8、传递性:如果A happens-before 于 B,且 B happens-before 于 C,则 A happens-before 于 C.
说明:
a:在同一个线程中,如果一个操作O1在时间上先于另一个操作O2发生,那么意味着O1 happen-before 于 O2操作. (虽然也存在指令重排序的情况(或者其它处理器对执行的优化操作),但它除了提高执行的效率外,不会产生其它影响.)
b:如果是多个线程的情况下,即便是一个操作O1先于另一个操作O2发生,但并不意味操作O1一定happens-before于另一个操作O2.
c:在多线程情况下,一个操作O1 happens-before于另一个操作O2,并不意味操作O1在时间上一定先于另一个操作O2.
线程安全的保证:
1、原子操作性.(对内存实施修改过程中不会被其它线程影响)
2、内存可见性.(对内存实施的修改可立即被其它线程看见)
为了保证所有线程都能看到共享的、可变变量的最新值,读取和写入线程必须使用公共的锁进行同步.或者是使用volatile来修饰(在一些特定的情况下才可用).
synchronized
锁不仅仅是关于同步和互斥的(可保证操作的原子性),也是关于内存可见的.
volatile变量:(保证可见性,但不能保证原子性.)
1、当被声明为volatile类型后,编译器编译及运行时都会监视这个变量:它是共享的,对它的操作不会与其它的内存操作一起被重排序,volatile变量不会缓 寄存器或者其它对处理器隐藏的地方.
2、volatile变量的操作不会加锁,也就不会引起执行线程的阻塞,相对于synchronized,它是轻量级的同步.
3、正确使用volatile的方式(用来确保它所修饰对象状态的可见性,或者用于标识重要的生命周期事件的发生)
a: 写入变量时并不依赖变量的当前值(如i++);或者能够确保只有单一的线程修改变量的值.
b: 该变量没有包含在具有其他变量的不变式中.
关于volatile可从http://www.ibm.com/developerworks/cn/java/j-jtp06197.html了解更多信息.
最低限安全性:
当一个线程在没有同步的情况下读取变量,它可能会得到一个过期值.但是至少它可以看到某个线程在该变量设定的一个真实数值.(可能是过期数据)这就叫最低限安全性. (非volatile的64数数值变量:double 和 long 例外,因为jvm允许将64位的读或者写划分为两个32位操作.)
对象的发布和逸出
1、发布:发布一个对象的意思是使它可以被当前范围以外的代码所使用.
2、逸出:如果发布对象时,这个对象还没有完成构造,这种情况称为逸出.
最常见的为this引用逸出.
导致this引用在构造期间逸出的常见错误,是在构造函数中启动一个线程.无论是显示(将线程传给构造函数)还是隐式(Thread或Runnable是所属对象的内部类),this引用几乎总是被新线程共享.
不可变对象:(不可变对象始终是线程安全的)
1、它的状态不能再创建后再被修改.
2、它所有的域都是final类型的.
3、它被正确创建(没有发生this引用逸出)
对象的不安全发布:
除了不可变对象以外,使用被另一个线程初始化的对象,是不安全的,除非对象的发布是hppens-before于对象的消费线程使用它.(保证不能发生逸出)
安全发布模式:为了安全地发布对象,对象的引用以及对象的状态必须同时对其它线程可见.一个正确创建的对象可以通过一下条件安全的发布:
1、通过静态初始化器初始对象的引用. (保证对象的初始化不发生逸出)
2、将它存储到volatile域或AtomicReference. (volatile可保证可见性,AtomicReference内部其实也是使用volatile加上CAS来实现的)
3、将它的引用存储到正确创建的对象的final域中.(fianl属性,不可变,只能在构造函数中初始)
4、将它的引用存储到由锁正确保护的域中. (用锁来保证可见性)
单例模式的几种正确实现:
1、饿汉式:
private Singleton instance = new Singleton();// 这个是由jvm的类加载来保证.
2、懒汉式同步方法:
public static synchronized Singleton getInstance(){}; // 对于每次调用都要加锁,而且还是类级别锁,性能问题.
3、惰性初始化并采用内部holder类技巧:(利用JVM类的初始化机制保证)
public class Singleton{
// 私有构造方法省略
private static class Holder{
public static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return Holder.instance; // 对类的主动使用将导致Holder的初始化,而对于类中的静态代码块、静态属性只会初始化一次(类级别).
}
}
4、DCL模式加volatile
关于热议的DCL模式存在的问题请查看:
http://www.iteye.com/topic/260515
参考书籍:java 并发编程实践
分享到:
相关推荐
书中会首先介绍Java并发编程的基础知识,包括线程的创建和运行,同步机制的基本用法,以及Java内存模型的相关概念。随着章节的深入,作者可能会更深入地讲解Java提供的并发工具,例如锁、原子变量、线程池、以及并发...
#### 一、并发编程基础概念 在《JAVA并发编程实践》这本资料中,我们首先需要理解并发编程的基本概念。并发编程是指在单个程序中同时执行多个任务的能力,这对于提高应用程序的性能至关重要。在Java中,主要通过...
综上所述,《深入理解并发编程》一书应涵盖并发编程的基础理论、内存模型、同步机制、多线程编程技巧、常见问题的解决方案以及高效编程实践。掌握这些知识,能够帮助开发者在多核处理器时代编写出既高效又稳定的并发...
通过阅读《Java并发编程的艺术》这本书,开发者不仅可以掌握Java并发编程的基础知识,还能了解到一些高级特性和技巧,从而在实际开发中游刃有余。同时,附带的源码将有助于加深理解,提供实际操作的机会。
总之,《Java并发编程实战》是一本全面介绍Java并发编程的书籍,适合有一定Java基础并希望提升并发编程能力的开发者阅读。通过学习,你可以掌握解决并发问题的策略和技巧,编写出更加健壮和高效的多线程应用。
第一部分介绍了并发编程的基础,包括线程安全性的概念,如何构建线程安全的类,以及Java平台提供的并发工具如线程、同步机制等。这部分内容有助于开发者理解并发编程的基本原理和最佳实践。 第二部分讨论了如何构建...
其次,书中深入剖析了Java内存模型(JMM)和可见性问题,这是理解并发编程中数据一致性问题的基础。Java的volatile关键字、synchronized块和方法、以及Atomic类都是解决这些问题的关键工具。作者通过实际案例解释了...
首先,第一部分“概念”作为基础,介绍了并发编程的高级概念,为读者理解并发的原理和重要性打下基础。这里涵盖了并发编程的一些基本概念,例如线程、进程、任务并行库、数据并行性、同步机制等。这些概念是设计并发...
#### 一、简介与并发编程基础 《C++并发编程实践》这本书由Anthony Williams编写,是一本深入讲解C++多线程编程技术的专业书籍。本书旨在帮助读者掌握C++中的并发编程技巧,并通过大量的示例代码来加深理解。 **...
本书不仅适合已经有一定Java编程经验的开发人员阅读,也适用于希望深入了解并发编程基础的新手。它从最基本的并发概念讲起,如进程与线程的区别、线程生命周期、线程调度策略等,并逐步深入到锁机制、死锁避免、原子...
本书首先会介绍Java并发编程的基础概念,包括线程的创建与管理、同步机制如synchronized关键字和Lock接口,以及如何避免常见的并发问题,如死锁、活锁和饥饿。这些基础知识是理解并发编程的基石,通过深入浅出的讲解...
这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者理解并掌握Java并发编程的核心概念和技术。 在Java并发编程中,首先我们需要了解的基本概念是线程。线程是操作系统分配CPU时间的...
Java并发编程是软件开发中的一个关键领域,尤其是在大型企业级应用和分布式系统中。通过学习相关的书籍,开发者可以深入理解如何有效地设计和实现高效的多线程应用程序,避免并发问题,如竞态条件、死锁、活锁等。...
《Java并发编程从入门到精通》作者结合自己10多年Java并发编程经验,详细介绍了Java并发编程的基础概念、工作原理、编程技巧和注意事项,对Java高性能高并发编程有极大的参考价值。 《Java并发编程从入门到精通》...
【深入理解高并发编程-核心技术原理】是一本专注于讲解高并发编程核心概念和技术的书籍,由阿里P8级别的架构师及Mykit系列开源框架作者撰写。本书内容涵盖源码分析、基础案例、实战案例和面试相关知识,旨在帮助读者...
而并发编程则是实现高并发的基础,它涉及到如何在多线程环境下有效地管理计算资源,以提高系统性能和响应速度。 线程安全是并发编程中的核心概念,确保多个线程在共享数据时不会引发错误或不一致状态。线程安全可以...
在本资源中,我们有两个主要的学习材料:一个关于“Java并发编程基础”的PPT和一个包含DEMO示例,另一个是“操作系统概述”的PPT。这些资料对于理解Java多线程编程以及操作系统的基础原理至关重要。 首先,让我们...
一、并发编程基础 并发是指两个或多个操作在同一时间段内执行,但并不意味着这些操作是并行的,即同时在不同处理器上执行。在Java中,主要通过线程实现并发,线程是操作系统调度的基本单位,每个线程都有自己的程序...