zoukankan      html  css  js  c++  java
  • 并发编程笔记1

    1、并发编程挑战

    1.1、上下文切换:

      1.1.1、什么是上下文切换?

        单核也支持多线程执行,原因是通过时间片轮换,时间片是CPU分配给各线程的时间,在切换过程中,会先保存上个任务信息,再加载当前任务信息,所以任务从保存到再加载的过程就是一次上下文切换。

      1.1.2、并行vs串行

        并发执行速度比串行慢的原因是:线程创建以及上下文切换的开销。

      1.1.3、查看上下文切换

        使用vmstat cs(content switch)

      1.1.4、如何减少上下文切换

      • 无锁并发编程。例如:将数据IDHash算法取模分段,特定线程处理特定段数据。
      • CAS算法。例如 Atomic包使用CAS算法更新数据,不需要加锁
      • 使用最少线程。  
      • l协程:在单线程里实现多任务调度。

      1.1.5、减少上下文切换实战

        可以通过减少线上大量WAITING的线程,减少上下文切换次数

    1.2、死锁

      产生死锁的原因:线程t1和线程t2互相持有并等待对方释放锁。

      发生死锁查看步骤:不能提供服务,dump线程查看哪个线程出现问题

      避免死锁方法:

        1、避免一个线程同时获取多个锁;

        2、避免一个线程在锁内占用多个资源,尽量保证只占每个锁占用一个资源。

        3、使用定时锁,如lock.tryLock(timeout)替代使用内部锁机制。

        4、对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

    1.3、资源限制的挑战

      (1) 什么是资源限制?

        硬件资源:带宽上传/下载速度,硬盘读写速度,CPU处理速度,内存

        软件资源:数据库连接,socket连接数等

      (2) 资源限制引发问题

        并发编程速度快原因:将代码中串行执行部分变成并发执行;若并发执行,由于资源限制就会串行化执行,就会增加上下文切换和资源调度的时间消耗。

      (3) 如何解决资源限制

        采用集群并行执行,例如hadoop,不同的机器处理不同的数据,“数据ID%机器数”,计算得到一个机器编号,然后由对应编号的机器处理这笔数据。

      (4) 资源限制下的并发编程

        根据不同的资源限制调整程序的并发度

        建议使用JDK并发包提供并发容器和工具类来解决并发问题

    2、Java并发机制的底层实现原理

    2.1Volatile

      2.1.1volatile的应用

      ① 保证共享变量“可见性”,可见性:当一个线程修改一个共享变量时,另外一个线程能读到这个修改值;

      ② 轻量级synchronized,执行成本更低,不会引起线程上下文切换和调度;

      ③ 避免指令重排;

      ④ 8字节(long,double),一次性赋值;

    2.1.2Volatile修饰变量,JIT编译生成汇编语言会加Lock前缀,从而引发两件事情:

      1)、将当前CPU缓存行的数据(工作内存)写回到系统内存(主存)

      2)、这个写回内存的操作会使其他CPU缓存该内存地址数据失效。

      缓存一致性:在多处理器下,每个处理器通过嗅探总线的数据来检查自己缓存的值是否过期,当发现自己缓存行对应的内存地址被修改,会将自己的缓存行数据设置无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中将数据重新读取。

    Volatile使用优化:LinkedTransferQueue

    2.2synchronized的实现原理和应用

      2.2.1synchronized基础

      ① Java中每一个对象都可以作为锁;

      ② 锁普通方法,锁是实例对象;

      ③ 锁静态方法,锁是当前类Class对象;

      ④ 锁同步代码块,锁是配置对象。

    JVM基本原理:使用Monitor对象,代码块同步是使用monitorentermonitorexit指令实现。

      2.2.2Java对象头

        对象头长度:Mark Word【锁状态,对象的hashCode,对象分代年龄,是否是偏向锁,锁标志位】

    2.2.3、锁的升级与对比

    锁状态:

    无锁状态,偏向锁,轻量级锁,重量级锁

    优点

    缺点

    适用场景

    偏向锁

    加锁和解锁不需要额外的消耗,和执行同步非同步方法性能差不多

    如果线程间存在锁竞争,会带来额外锁撤销的消耗

    适用于只有一个线程访问同步块场景

    轻量级锁

    竞争的线程不会阻塞,提高了响应速度

    如果始终得不到锁竞争的线程,使用自旋会消耗cpu

    追求响应时间

    同步块执行速度非常快

    重量级锁

    线程竞争不使用自旋,不会消耗cpu

    线程阻塞,响应时间缓慢

    追求吞吐量,同步块执行速度较长

    2.3 原子操作的实现原理

      原子操作:不可被中断的一个或一系列操作。

      CAS(Compare and Swap):CAS操作需要输入两个数值,一个旧值(期望操作前的值),和一个新值,在操作期间先比较旧值有没有发生变化,如果没有发生变化,才交换心志,发生了变化则不交换。

    2.3.1、处理器如何实现原子操作:

      (1) 使用总线锁保证原子性;

      (2) 使用缓存锁保证原子性;

    2.3.2Java如何实现原子操作

      ① 使用循环CAS实现原子操作,如Java并发包中Atomic提供

      ② CAS实现原子操作问题

        1) ABA问题,解决方法:AtomicStampedReference就是每个更新把版本号加1

        2) 循环时间长开销大;

        3) 值能保证一个共享变量的原子操作,(取巧方法,把多个共享变量合并成一个共享变量来操作,如i=2,j=a,合并为ij=2a

  • 相关阅读:
    zombodb 数据类型映射
    Amundsen — Lyft’s data discovery & metadata engine
    The Twelve-Factor Container
    zombodb sql functions 说明
    zombodb 得分以及高光
    windows openssh 设置root 目录
    zombodb 聚合函数
    zombodb 索引管理
    zombodb 索引创建
    zombodb 低级api 操作
  • 原文地址:https://www.cnblogs.com/atomicbomb/p/10083417.html
Copyright © 2011-2022 走看看