四,并发编程 - 348052148/learnGraph GitHub Wiki

并发编程

一,并发 和 并行的概念 并发是同时做多件事情,并行是同一时间做多件事情 并发执行可以是串行的,也可以是并行的, 并发属于问题域,并行属于方法域

二,多线程编程痛点 (导火索-线程之间需要同步

  1. 频繁的上下文切换(性能
  2. L3缓存失效
  3. 共享内存时,内存同步问题
  4. 饥饿-活锁-死锁 (可用性

三,死锁出现的必要条件

  1. 相互排斥,具有独占权
  2. 条件等待,进程必须拥有一个资源并且同时等待其他资源
  3. 不可抢占
  4. 循环等待。
  • 四,并发编程为什么这么难 (不可变解决所有问题
  1. 竞争条件
  2. 依赖顺序
  3. 内存同步
  4. 原子性

五,java并发编程相关

  1. Jvm 内存模型,jvm有主内存,负责所有线程共享数据,每个线程有自己的私有内存区,主内存和工作内存分别在jvm的stack 和 heap区
  2. 线程等待原因,进行io操作阻塞,试图获取锁
  3. 对原子性的理解要考虑到底层jvm指令
  4. Volatile变量 来增加内存屏障禁止指令重排,同时直接写入到主内存触发刷新到工作内存,并不能保证原子性,只能保证内存可见性
  5. sleep和wait区别,wait会解除锁定,sleep只是给出cpu
  6. 异步编程 + 事件驱动 来替代多线程

六,jvm内存模型

  1. 主内存 和 工作内存
  2. 内存交互操作,lock, unlock, read, load, use,assign,store,write
  3. Volatile 保证可见性,禁止指令重排
  4. long/double 64位,分2次,不具备原子性
  5. 原子操作。read、load、assign、use、store、write 可见性。有序性
  6. 指令重新排序,重排屏障
  7. 先行发生原则,来保证单线程的顺序性

七,异步编程

  1. node.js 的异步回调。(其底层实现一个事件处理进程进行事件轮训

八,响应式编程

九, CSP模型 & Actor模型 & Reactor 模型 Reactor 关于同步异步阻塞非阻塞io

十,同步,异步,阻塞,非阻塞 (比较微观的底层

  1. 同步,请求后等待结果
  2. 异步,请求后,结果有了进行通知
  3. 阻塞,调用后等待返回
  4. 非阻塞,调用后不等待返回
  5. 异步io和同步io,数据拷贝时,进程是否阻塞,阻塞io和非阻塞io,程序是否阻塞
  6. 5种io,阻塞io,非阻塞io(依靠轮询,io复用(等待多个io可读(降低阻塞情况),拷贝数据的时候阻塞,信号驱动(拷贝数据阻塞,异步io(完全异步,可读拷贝完成后进行通知
io多路复用是指一个进程可以同时监听多个文件描述符,当其中有一个或多个文件描述符可读或可写的时候,内核会唤醒这个进程
基本元素
{
    fd 文件描述符
    waitProcessQueue 等待进程队列(阻塞
}
{
   process 可执行进程 (进程可重新获取时间片
}
select/poll 模式,每次进行setFds 将进程设置进各个文件描述符的等待队列里。这时进程阻塞。当其中有一个或多个的fds准备好了,内核便将进程从 fd的等待进程队列中移除 加入到执行进程队列中。
fds什么时候准备好呢?
如果是网络socket,网络数据网卡拷贝到内存完毕时,便可以通知准备好了。 流程大概是 网卡接受到数据,出发网卡中断,内核处理中断程序将网卡数据拷贝到内存,然后将等待io的进程加入可执行进程列表,进行再调用系统call,一般是 read,将数据从内核 拷贝到用户内存空间,在这个过程中。阻塞的主要有2部分,等待io数据,拷贝io数据到用户内存空间
//select 每次都必须重新设置一遍讲进程加入fds的操作。因为每次io准备好了都会把进程从fds等待队列中移除。
epoll 模型
{
    fds_ready_list
}
epoll 相当于新创建了一个结构,(想起一句在jdon看到的话,没什么是不能加一个抽象层来处理的。如果不行,再抽象一层?)
调用epoll_create时,做了以下事情:
1. 内核帮我们在epoll文件系统里建了个file结点;
2. 在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket;
3. 建立一个list链表,用于存储准备就绪的事件。
调用epoll_ctl时,做了以下事情:
1. 把socket放到epoll文件系统里file对象对应的红黑树上;
2. 给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪list链表里。
调用epoll_wait时,做了以下事情:
观察list链表里有没有数据。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。而且,通常情况下即使我们要监控百万计的句柄,大多一次也只返回很少量的准备就绪句柄而已,所以,epoll_wait仅需要从内核态copy少量的句柄到用户态而已。
调用epoll_wait时,做了以下事情:
观察list链表里有没有数据。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。而且,通常情况下即使我们要监控百万计的句柄,大多一次也只返回很少量的准备就绪句柄而已,所以,epoll_wait仅需要从内核态copy少量的句柄到用户态而已。
..所以epoll 依然会存在内核态数据拷贝到用户态阻塞的问题。

十一,select ,epoll 详细 aio

十二,goruntine 绿色线程实现

  1. 1:1 一个协程对于一个线程
  2. N:1 n个协程对应一个线程
  3. N:M M个线程任意调度 goruntine实现

十三,并发模型

悲观锁
  1. 同步锁
  2. 自旋锁
  3. 可重入锁
  4. 读写锁
乐观锁 和 无锁
  1. CAS
  2. Copy On Write
  3. 原子类
  4. 线程本地存储(java
  5. 不变模式