当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

并发编程基础概念

发表于: 2012-03-16   作者:ag_sherry   来源:转载   浏览:
摘要: JMM:java存储模型1、java语言规定jvm要维护内部线程类似顺序化语意:     程序的执行的最终结果要等同于它在严格的顺序化环境中的执行结果. 2、JMM规定jvm的一种最小保证:什么时候写入一个变量的值对其它线程可见. 3、重排序(在编译时、运行时、硬件进行存储操作时都有可能发生重排序). 4、java存储模型定义了一些行为,所谓行为包括:

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 并发编程实践 

 

 

 

 

并发编程基础概念

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
Java 并发编程基础 1. 线程 的风险 1.1 安全风险 线程不安全: Public class UnsafeSequence{ Priva
原文链接: http://blog.csdn.net/historyasamirror/article/details/4270633 作为程序员从应用层面
主要内容如下: 简介网络模型以及相关的socket编程 简介多进程编程 简介多线程编程 简介I/O复用 通过
TCP协议分成两个不同的协议: 1、网络传输中差错的传输控制协议TCP 2、专门负责对不同网络进行互联
C++11标准在标准库中为多线程提供了组件,这意味着使用C++编写与平台无关的多线程程序成为可能,而C
正文 C++11标准在标准库中为多线程提供了组件,这意味着使用C++编写与平台无关的多线程程序成为可能
Java提供了三个并发编程功能包,它们是: java.util.concurent java.util.concurent.locks java.util
作者:摇摆少年梦 视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 Scala并发编程简介
并发所描述的概念就是同时运行多个任务。这些任务可能是以在单核 CPU 上分时(时间共享)的形式同时
本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自【黑米GameDev街区】 原文链接: http:
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号