高并发网课的笔记

CH01

  • 并发:多个线程操作相同的资源,保证线程安全,合理使用资源
  • 高并发:服务能同时处理很多请求,提高程序性能

CH02

  • CPU中有多级缓存(CPU远比主存快),可保证是时间局部性和空间局部性
  • 多级缓存的缓存一致性(MESI):四个状态
    • Modified: 被修改过的,需要在未来某个时刻重新写回主存,在这之间允许其他CPU读取
    • Exclusive: 未被修改的,与主存状态一致
    • Shared: 共享状态,可能被多个CPU进行缓存,与主存数据一致
    • Invalid: 当有CPU修改该缓存行时,进入此无效态
  • 多级缓存的乱序优化: 处理器为提高运算速度而做出违背代码原有顺序的优化
  • JMM: 每个线程都拥有数据的私有拷贝
  • JMM同步八种操作:
    1. 锁定: 作用于主内存的变量,标示为线程独占
    2. 解锁: 作用于主内存的变量
    3. 读取: 作用于主内存,从主内存输送到工作内存
    4. 载入: 作用于工作内存, 放入到变量副本中,与读取必定顺序
    5. 使用: 输送给执行引擎
    6. 赋值: 从执行引擎到工作内存
    7. 存储: 工作内存到主内存
    8. 写入: 工作内存写入主内存,与存储必定顺序

CH03

  • 并发模拟工具:
    1. Postman: Http请求模拟工具。在Collection的run中测试
    2. Apache Bench: 测试网站性能, terminal工具。用法: ab -n 1000 -c 50 http://localhost:8080/test
    3. JMeter(首选): Apache组织开发的压力测试工具
    4. 代码: Semaphore

CH04

  • 线程安全性:
    1. 原子性: 互斥访问. e.g. Atomic包
    2. 可见性: 一个线程对主内存的修改可以及时的被其他线程看到
    3. 有序性: 一个线程观察其他线程中的指令执行顺序, 由于指令重排, 该观察结果一般杂乱无序
  • Atomic里面unsafe类, 提供了 getAndAddInt() 方法, 具体实现使用了compareAndSwapLong()方法, 是Java的native方法. 整个getAndAddInt()方法的关键是不停判断从主存读回来的值和当前主存的值相同, 才写入新的值(CAS操作), 否则循环. 当CAS操作失败几率高时, 性能会下降
  • Atomic里面的LongAdder比AtomicLong高效, 思想是把64位int转成Cell数组, 降低对value更新的并发数,也就是将对单一value的变更压力分散到多个value值上,降低单个value的“热度”.
  • 锁:
    • synchronized: 以来JVM
    • Lock: 依赖特殊的CPU指令
  • synchronized:
    1. 修饰代码块: 作用于调用的对象, 实验结果是不同实例调用该方法是非同步的
    2. 修饰方法: 作用于调用的对象, 实验结果是不同实例调用该方法是非同步的
    3. 修饰静态方法: 作用于所有对象, 实验结果是不同实例调用该方法是同步的
    4. 修饰类: 括号括起来的部分, 作用于所有对象, 实验结果是不同实例调用该方法是同步的
  • synchronized是不能继承的, 子类想要有必须自己显式写明
  • 可见性:
    • 不可见的原因(结合JMM模型理解):
      1. 线程交叉执行
      2. 重排序结合线程交叉执行
      3. 共享变量更新后的值没有在工作内存与主存及时更新
    • synchronized的可见性:
      1. 线程解锁前, 必须把共享变量的最新值刷新到主内存
      2. 线程加锁时, 将清空工作内存中共享变量的值, 从而使用共享变量时需要从主内存中重新读取最新的值
      • PS: 这里说的锁是同一把锁, 因此不同类之间不会相互影响
    • volatile保证可见性
      1. 加入内存屏障和禁止重排序
      2. volatile的读写操作直接与主存相关(但还是会有工作内存, 只是修改完直接刷新)
      • PS: 更适合用来做判断标记量
  • 有序性: happens-bofore原则

猜你喜欢

转载自blog.csdn.net/qq_18122705/article/details/84849539