美文网首页
Java并发(01)-总体概要

Java并发(01)-总体概要

作者: 小亮__ | 来源:发表于2019-06-27 07:24 被阅读0次
    并发应用

    Java 并发问题的产生

    Java内存模型(JMM)规定所有的变量都是存在主存当中(类似物理内存),每个线程都有自己的工作内存(类似于高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存,当多个线程同时向主存读取和写入的时候,便会出现并发问题

    并发编程中要保证的三个原则

    原子性:线程对于内存中的数据的--读取和写入保持原子性
    可见性:A线程改变物理内存的值,需要让B线程知道
    有序性:代码的执行顺序(因为CUP为了提高代码的执行顺序,会打乱代码的执行顺序,只会保证单线程的最终一致性)

    JAVA保证并发编程中的三个概念的机制

    • 原子性:使用Lock, synchronized关键字来保证操作的原子性

    • 可见性: 当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存, 另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

    • 有序性:在Java里面,可以通过volatile关键字来保证一定的“有序性”。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。

    happens-before原则

    除了上面所说的可以使用volicate和加锁来保证有序性,Java内存模型具备一些先天的“有序性”,即不需要通过任何手段就能够得到保证的有序性,这个通常也称为 happens-before 原则。如果两个操作的执行次序无法从happens-before原则推导出来,那么它们就不能保证它们的有序性,虚拟机可以随意地对它们进行重排序,下面就来具体介绍下happens-before原则(先行发生原则)

    • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
    • 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
    • volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
    • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
    • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
    • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
    • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
    • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始

    synchronized:

    • 实现原理:(synchronized(object)时)
    • 每个对象有一个监视器锁(monitor),线程通过monitorenter和monitorexit命令,获得锁
    • 如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,线程已经占有该monitor,只是重新进入则进入的同时monitor的进入数加1
    • 如果线程调用monitorexit时,mointor进入数减一,当mointor进入数为0时,其他线程可以进入

    详细介绍:https://www.jianshu.com/p/d40eb583f5c4

    volatile关键字:

    • 使用volatile关键字会强制将修改的值立即写入主存,并让其他线程的运行时内存的该变量值无效(使用时重新读取主存)
    • 只能保证每次读取的是最新的值,但是volatile没办法保证对变量的操作的原子性(写入一致不能保证)

    详细介绍:https://www.jianshu.com/p/91f0c6dd2551

    Lock:

    • 相对与synchronized好处:Lock可以等待一段时间后自动释放锁(例如IO操作时间过长时)
    • 相对与synchronized好处:Lock可以知道线程是否获得锁
    • 相对与synchronized好处:Lock可以使用读写锁来增加效率
    • ReentrantLock的实现原理就是根据AQS的机制实现的

    AQS 机制:

    • 假设线程A要获取同步状态(这里想象成锁,方便理解),初始状态下state=0,所以线程A可以顺利获取锁,A获取锁后将state置为1。在A没有释放锁期间,线程B也来获取锁,此时因为state=1,表示锁被占用,所以将B的线程信息和等待状态等信息构成出一个Node节点对象,放入同步队列,head和tail分别指向队列的头部和尾部(此时队列中有一个空的Node节点作为头点,head指向这个空节点,空Node的后继节点是B对应的Node节点,tail指向它),同时阻塞线程B(这里的阻塞使用的是LockSupport.park()方法)。后续如果再有线程要获取锁,都会加入队列尾部并阻塞。

    CAS的实现原理:

    • CAS(比较与设置)主要应用在concurrent包中的AtomicXXX的实现
    • CAS通过调用JNI的代码实现的( JNI:Java Native Interface为JAVA本地调用,允许java调用其他语言)
    • 所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
    • CAS还是会存在ABA问题,这是就需要通过加入版本号来解决该问题
      详细介绍:https://www.jianshu.com/p/9a4b9e846ae4

    Atomic工具包

    • java 在 1.5 版本中提供了 java.util.concurrent.atomic 包,该包下所有的类都是原子操作,其内部使用的原理就是cas算法

    并发工具类--- ThreadLocal

    • JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序
    • 用于线程间的数据隔离。所以ThreadLocal的应用场合,最适合的是按线程多实例(每个线程对应一个实例)的对象的访问

    详细地址:https://www.jianshu.com/p/1f61faa88861

    并发容器类--- ConcurrentHashMap

    并发容器类--- CopyOnWriteArrayList

    并发工具类---ThreadPoolExecutors(线程池)

    线程池工具类,固定大小线程池,单任务线程池,可变线程池

    • 核心组件:

      • corePoolSize:核心线程池的大小
      • maximumPoolSize:最大线程池的大小
      • keepAliveTime:线程没有任务时的存活时间
      • workQueue:用于存储任务的,阻塞队列
      • threadFactory:线程工厂,用于创建线程
      • handler:线程的处理策略()
    • 饱和策略:

      • AbortPolicy:中止,executor抛出未检查RejectedExecutionException,调用者捕获这个异常,然后自己编写能满足自己需求的处理代码。
      • DiscardRunsPolicy:遗弃最旧的,选择丢弃的任务,是本应接下来就执行的任务。
      • DiscardPolicy:遗弃会默认放弃最新提交的任务(这个任务不能进入队列等待执行时)
      • CallerRunsPolicy:调用者运行,既不会丢弃哪个任务,也不会抛出任何异常,把一些任务推回到调用者那里,以此减缓新任务流。它不会在池线程中执行最新提交的任务,但它会在一个调用了execute的线程中执行。

    并发工具类---Semaphore(信号量)

    • 主要用于控制多线程对共同资源库访问的限制
    • 例如 地下车位,要有空余才能放行, 开会的例子:会议室里等与会人员到齐了会议才能开始

    并发工具类---CountDownLatch( 计数器)

    • 比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了

    并发工具类--- CyclicBarrier

    • 类似CountDownLatch,CyclicBarrier可以多次使用,CountDownLatch只能用一次(为0后不可变)

    JAVA实现多线程的常用技术阶梯

    技术阶梯

    相关文章

      网友评论

          本文标题:Java并发(01)-总体概要

          本文链接:https://www.haomeiwen.com/subject/wrezqctx.html