• java并发编程


      三个概念的理解:程序、进程和线程

        程序:静态实体

        进程:动态实体,存于内存,又叫任务,是程序的运行时期

        线程:进程创建的更小粒度

      编写线程安全的代码,本质上就是管理对状态的访问,而且通常都是共享的、可变的状态。所谓共享是指一个变量被多个线程访问;所谓可变是指变量的值在其生命周期内可以改变。

      线程安全这个性质取决于程序中如何使用对象,而不是对象完成了什么。一开始就将类设计为线程安全的,比在后期修改他更容易。

    一、概念

      1、线程安全类:当多个线程访问一个类时,如果不用考虑线程在运行时的调度和交替执行,并且不用额外的同步机制作为协调,这个类的行为仍然是正确的,那么我们说这个类为线程安全的。

        示例:无状态类——它不包含域也没有引用其他类的域。无状态对象永远是线程安全的。

        解释:无状态对象只有一些方法,方法内部的局部变量会存到相应线程的堆栈中,每个线程的堆栈是独立的。

      2、原子性:当其他线程想要访问查看或者修改一个状态时,必须在我们的线程开始之前或者完成之后,而不能在操作过程中。

         原子操作:要么都执行,要么都不执行

         原子变量类:java.util.concurrent.atmoic里提供的原子变量类。类的小工具包,支持在单个变量上解除锁的线程安全编程。

      3、java的内置的原子性机制——锁:synchronized块。块包含两部分:锁对象的引用,这个锁要保护的代码块。

        3.1内部锁

        3.2重进入

           线程请求自己占有的锁时,请求会成功。

      4、用锁来保护状态

        操作共享状态的复合操作必须是原子操作。复合操作会在完整的运行期间占有锁,以确保其行为是原子的。

      5、活跃度与性能

        过于强调安全就会出现性能下降,过度强调安全,就会导致不必要的等待。

    二、共享对象

       1、可见性

         为了确保跨线程写入内存的可见性,必须使用同步机制。只要数据需要跨线程共享,就进行恰当的同步。

         1.1过期数据

            没有进行恰当的线程同步机制,导致一个线程对共享数据的修改,并不能保证其余的线程是可见的。

         1.2非原子的64位操作

            java的存储模型要求存储和读取操作都为原子的,但是对于非volatile的long和double变量,JVM允许将64位的读或写划分为两个32位的操作。因此,在多线程中共享、可变的long和double变量也可能是不安全的,除非将他们声明为volatile类型,或者用锁保护起来。

         1.3锁和可见性

            锁不仅仅是关于同步和互斥的,也是关于内存可见性的。为了保证所有线程都能看到共享变量的最新值,读取和写入线程必须使用公共的锁进行同步。

         1.4volatile变量

            volatile相比锁而言,只是一种轻量级的同步机制。

            volatile变量的典型应用:检查状态标记,以确定是否退出一个循环。

            volatile也有缺点:volatile的语义并不能保证自增操作是原子操作。加锁可以保证原子性和可见性,volatile变量只能保证可见性

       2、线程封闭

          2.1栈限制

            栈限制是线程限制的一种特例,在栈限制中,只能通过本地变量才可以触及对象。每个线程都有自己的堆栈,本地变量基本上都存储与自己的堆栈,每个线程的堆栈是不会有冲突的,其他线程是不会访问到的,本地变量是线程封闭的。

          2.2ThreadLoacl

            一种维护线程限制的更加规范的形式,它允许将每个线程与持有数值的对象关联起来。ThreadLocal提供了get和set访问器,为每个使用他的线程维护一份单独的拷贝。其实和线程池差不多。

        3、不可变性

          不可变对象永远是线程安全的。不可变对象是简单的。

          不可变对象的条件:

            ①他的状态不能再创建后修改(对“状态”的理解:对象的引用)

            ②所有的域都是final类型

          使用volatile发布不可变对象:用不可变容器再加上volatile关键字发布不可变对象。具体代码如下    

     1 @immutable
     2 public class OnerValueCache {
     3     
     4     private final BigInteger lastNumBigInteger;
     5     private final BigInteger [] lastFactorsBigIntegers;
     6     
     7     public OnerValueCache(BigInteger num,BigInteger[] factors){
     8         lastNumBigInteger=num;
     9         lastFactorsBigIntegers=Arrays.copyOf(factors,factors.length);
    10     }
    11     
    12     public BigInteger[] getFactors(BigInteger num){
    13         if(lastNumBigInteger==null||!lastNumBigInteger.equals(num)){
    14             return null;
    15         }
    16         return Arrays.copyOf(lastFactorsBigIntegers, lastFactorsBigIntegers.length);
    17     }
    18 }
    View Code
     1 @ThreadSafe
     2 public class VolatileCachedFactorizer implements Servlet{
     3   private volatile OnerValueCache cache=new OnerValueCache(null,null); 
     4   public void service(){
     5     BigInteger i =extractFromRequest(req);
     6     BigInteger Factors=cache.getFactors(i);
     7     if(factors==null){
     8        factors=factor(i);
     9        cache=new OnerValueCache(i,factors);  
    10     }
    11     encodeIntResponse(resp,factors);
    12   }   
    13 }    
    View Code
  • 相关阅读:
    索引与完整性约束(note6)
    数据库查询语句(note4)
    select 查询(note3)
    数据库创建(note2)
    mysql(note1)
    day 05
    day 04 字符串
    博文索引
    ubuntu+xen的编译
    hexo+github搭建个人网站
  • 原文地址:https://www.cnblogs.com/sylz/p/5959901.html
Copyright © 2020-2023  润新知