Better

Ethan的博客,欢迎访问交流

计算机基础中两幅重要的图

计算机各部件运行速度和存储器结构,了解计算机系统的各种问题以及相应的解决方案。

两幅图

计算机各部件运行速度 WechatIMG248.jpeg

表的第三列将成本转换为我们理解的时间尺度,即秒、分、日、月和年的时间尺度。在这里,操作的成本是按比例缩放的,假设CPU周期的成本是1秒,而不是其他操作的成本。

存储器的层级结构 WechatIMG249.jpeg

正是由于计算机各个部件的速度不同,容量不同,价格不同,导致了计算机系统/编程中的各种问题以及相应的解决方案。以下是几个例子

案例

CPU 速度超级快,不能老是让它闲着,要充分压榨它。这里有两个强劲理由

  • 人类需要多个程序同时『运行』:CPU 时间分片,各个程序在 CPU 上轮转,造成多个程序同时在运行的假象,即『并发』
  • 当 CPU 需要 IO 操作(硬盘、网络)时,不能干等
    • 等待的时候,一定要切换,去执行别的程序,程序切换的时候需要保存程序执行的现场,以便以后恢复执行,于是需要一个数据结构来表示,这就是『进程』
    • 如果一个进程只有一个执行流,如果进程去等待硬盘操作的时候,那程序就会被阻塞,无法响应用户的输入,所以必须有多个执行流,即『线程』

需要持久化的数据一定要保存到硬盘中,但是硬盘超级慢,支持不了大量的并发访问,那怎么办

  • 最长访问的热点数据放到 CPU 缓存中,但 CPU 缓存实在太小,无法满足需求
  • 退而求其次,把热点数据放到速度稍慢的内存中,于是就出现了应用程序的缓存

Tomcat 应用服务器,对于每个请求都要用一个线程来处理,如果有一万个请求进来,会创建一万个线程来处理吗

  • 显然不会,因为线程多了,开销会很大,线程切换会很慢,因此使用线程池来复用
  • 如果线程都因为访问硬盘、数据库或网络调用,导致线程池被耗尽了,怎么办呢
  • 仅使用几个线程,比如和 CPU 核心数量一样,遇到 IO 操作,程序就注册一个钩子函数放在那里,线程就去处理别的请求,等到 IO 操作完成了,系统会给这个线程发送一个事件,线程调用之前的钩子函数来处理,这就是『异步,非阻塞』的处理方式,Node.js 和 Vert.x 都采用类似的思想

Redis 使用单线程的方式来处理请求的

  • 其面对的是内存,内存速度在计算机体系中仅次于 CPU,因此可以快速的执行内存的读写操作
  • 单线程巨大的优势:没有竞争,不需要加锁

来源

码农翻身



留言