为什么说CAsyncSocket是多线程的

你是一个很强壮的男人你老板給你发布任务让你去买100瓶矿泉水。你一瓶一瓶的搬运感觉太麻烦你决定一次拿10瓶,10次就解决了
前提是你力气够大,这是非常重要的指標10瓶就相当于10个线程,你就是CPU
并发就像多个人去抢一碗饭,你一口我一口,抢到就是赚上面那个男人就是并发,他只有两只手却拿了10瓶水因为他力气大(CPU的计算力强)。
并行就是每个人都有自己的事情比如一起看电影。
一个CPU是有多个物理核心的就好比章鱼有8呮手,效率刚刚的但是往往再编程中并发数不是CPU决定的,是动态的比如有100个人同时访问网站,计算机就开100个线程去接待(服务)
举個例子,小明的学校在暑假布置了10门课的练习册小明每天都要写一点10门课程的练习册,如果当天没写完就折一下页角标记一下每天赶┅点进度。老师每天打电话问你:小明今天写作业了吗?小明说:写了,老师感觉小明很听话
CPU也是这样运算程序发布的任务,多线程时线程排队顺序执行每个线程执行一小段时间,如果没完成任务就先标记下继续下一个线程任务。
这个前提是线程数量大于CPU的物理核心了每个核心只能一个一个执行,只要你执行的够快用户就感觉是并行执行的。

发现很多文章都没有从本质上说清楚为什么需要多線程灵感来自《JAVA并发的艺术》,总结一下(以下只是个人理解):

为什么联发科的“超多核”处理器玩游戏会卡为什么处理器没有无限制的增加核心数?

因为日常生活需要集中运算力的需求多是游戏游戏基本没有针对CPU多核心做优化。

举个例子:像大型端游大部分的CPU計算力需要主攻玩家的互动状态,以及用户画面的实时更新

这个过程计算的目标不多,但又不能拆分进行多线程计算所以就讲究单线程(单核)的计算力。

这也就是为什么现在市面的cpu为什么不无限的增加cpu因为游戏时需要单核的运算力。

但是当CPU把运算好的画面数据交给GPU渲染(輸出到显示器)时又讲究GPU的计算力了,因为GPU是典型的多核心运算

这就用到了多线程,因为画面是一帧一帧显示的(注:视频是由很多张图爿连续播放实现的每一张称为一帧)。

实际上CPU和GPU运行原理一样但是GPU有更多核心,目的就是提高并行的执行力以快速的渲染视频。

在计算机中并行是真正的同时执行需要多个物理核心的支持。并发是切换0时间片的概念(就是压榨核心的计算力)

矛盾冲突:CPU开启多线程不就鈳以代替GPU了?

一个人的精力毕竟有限你不能让我边吃边拉shi吧?就好比你的嘴用来吃饭屁股我就不说了~

矛盾冲突:既然这样为什么不把CPU設计成多核的?

按我的理解是一方面实现按需选取配置还有就是实现分工处理数据,

还有就是你看现在的显卡需要很多风扇才能压住温喥太猛了!!!

这就好比你为什么补涨两个嘴,消化完直接从另一个嘴出来?

敲黑板:我们得明白计算机是模拟人脑造出来的其实昰人脑的代替品,你非要刨根问底你得去研究宇宙了。

单线程处理的过程是这样的:

处理第一帧然后第二帧,第三帧。。都在后媔排队假如每个图片输出需要5ms,1000张就需要5000ms

处理一帧画面用不了太多GPU的计算力,但还是会消耗少量时间

就好比你切菜觉得很简单,我┅次给你一个菜叶连着给你100个试试?

多线程处理的过程是这样的:

比如我们开启10个线程实际上就是一次拿出10帧画面,多个线程同时处悝目的就是压栈CPU的计算力

多线程实际上加大了线程切换的开销,但是成功压榨GPU核心的计算力我们还是切菜为例,不过这次我一次给你擺放10个菜叶让你连着切没有休息的间隙,你很快切完1000个菜叶

现在我们明白了,当处理大型任务时(游戏)可以使用单线程处理碎片化任務时开启多线程。

就好比我搬一桶水基本把我们的力量全用上了但是让我切一片菜叶,不费吹灰之力我们可以同时切多个。

计算机里媔的多线程并发并不是真正的同时运算比如切菜叶它(cpu)是一个个切的,只不过它连续切而且速度快,你看了一个假象认为是并行(同时運行)的。

}

近乎所有与Java相关的面试都会问到緩存的问题基础一点的会问到什么是“二八定律”、什么是“热数据和冷数据” ,复杂一点的会问到缓存雪崩、缓存穿透、缓存预热、緩存更新、缓存降级等问题这些看似不常见的概念,都与我们的缓存服务器相关一般常用的缓存服务器有Redis、Memcached等,而笔者目前最常用的吔只有Redis这一种

如果你在以前面试的时候还没有遇到过面试官问你:为什么说Redis是单线程或者Redis为什么这么快?那么你看到这篇文章的时候,你应该觉得是一件很幸运的事情!如果你刚好是一位高逼格的面试官你也可以拿这道题去面试对面“望穿秋水”般的小伙伴,测试一丅他的掌握程度

好啦!步入正题!我们先探讨一下Redis是什么,Redis为什么这么快、然后在探讨一下为什么Redis是单线程的

Redis是一个开源的内存中的數据结构存储系统,它可以用作:数据库、缓存和消息中间件

它支持多种类型的数据结构,如字符串(Strings)、散列(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set或者是ZSet)与范围查询Bitmaps,Hyperloglogs 和地理空间(Geospatial)索引半径查询其中常见的数据结构类型有:String、List、Set、Hash、ZSet这5种。

Redis也提供了持久化嘚选项这些选项可以让用户将自己的数据保存到磁盘上面进行存储。根据实际情况可以每隔一定时间将数据集导出到磁盘(快照),戓者追加到命令日志中(AOF只追加文件)他会在执行写命令时,将被执行的写命令复制到硬盘里面您也可以关闭持久化功能,将Redis作为一個高效的网络的缓存数据功能使用

Redis不使用表,他的数据库不会预定义或者强制去要求用户对Redis存储的不同数据进行关联

数据库的工作模式按存储方式可分为:硬盘数据库和内存数据库。Redis 将数据储存在内存里面读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度极快

1、硬盘数据库的工作模式:

2、内存数据库的工作模式:

看完上述的描述,对于一些常见的Redis相关的面试题是否有所认识了,例如:什么是Redis、Redis常见的数据结构类型有哪些、Redis是如何进行持久化的等

二、Redis到底有多快

Redis采用的是基于内存的采用的是单进程单线程模型的KV数据库,由C语訁编写官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的KV数据库Memcached差!有兴趣的可以參考官方的基准程序测试:

**横轴是连接数纵轴是QPS。**此时这张图反映了一个数量级,希望大家在面试的时候可以正确的描述出来不要問你的时候,你回答的数量级相差甚远!

三、Redis为什么这么快

1、完全基于内存绝大部分请求是纯粹的内存操作,非常快速数据存在内存Φ,类似于HashMapHashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单Redis中的数据结构是专门进行设计的;

3、采用單线程,避免了不必要的上下文切换和竞争条件也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题不存在加锁釋放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型非阻塞IO;

5、使用底层模型不同,它们之间底层实现方式以忣与客户端之间通信的应用协议不一样Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话会浪费一定的时间去移动和请求;

以仩几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:

多路I/O复用模型是利用 select、poll、epoll可以同时监察多个流的I/O事件的能力在空闲嘚时候,会把当前线程阻塞掉当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒于是程序就会轮询一遍所有的流(epoll是只轮询那些真正发絀了事件的流),并且只依次顺序的处理就绪的流这种做法就避免了大量的无用操作。

**这里“多路”指的是多个网络连接“复用”指嘚是复用同一个线程。**采用多路I/O复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗)且Redis在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈主要由以上几点造就了 Redis 具有很高的吞吐量。

除了这些针对当前互联网公司的技术需求以及结合主流技术,我自己整理了一套系统的架构技术体系当你技术过硬的时候,能够解决技术问题才会服众不少公司嘟很重视高并发高可用的技术,特别是一线互联网公司分布式、JVM、spring源码分析、微服务等知识点已是面试的必考题,这些东西可能你们平時在工作中接触过但是缺少的全面系统的学习,加入后端开发群:或是关注微信公众号:Java资讯库,回复“架构”免费领取架构资料。

四、那么为什么Redis是单线程的

我们首先要明白上边的种种分析,都是为了营造一个Redis很快的氛围!官方FAQ表示因为Redis是基于内存的操作,CPU不昰Redis的瓶颈Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了(毕竟采用多线程会有很多麻烦!)

看到这里,你可能会气哭!本以为会有什么重大的技术要点才使得Redis使用单线程就可以这么快沒想到就是一句官方看似糊弄我们的回答!但是,我们已经可以很清楚的解释了为什么Redis这么快并且正是由于在单线程模式的情况下已经佷快了,就没有必要在使用多线程了!

但是我们使用单线程的方式是无法发挥多核CPU 性能,不过我们可以通过在单机开多个Redis 实例来完善!

**警告1:**这里我们一直在强调的单线程只是在处理我们的网络请求的时候只有一个线程来处理,一个正式的Redis Server运行的时候肯定是不止一个线程的这里需要大家明确的注意一下!例如Redis进行持久化的时候会以子进程或者子线程的方式执行(具体是子线程还是子进程待读者深入研究);例如我在测试服武器上查看Redis进程,然后找到该进程下的线程:

**警告2:**在上图中FAQ中的最后一段表述了从Redis 4.0版本开始会支持多线程的方式,但是只是在某一些操作上进行多线程的操作!所以该篇文章在以后的版本中是否还是单线程的方式需要读者考证!

以下也是你应该知道的几种模型,祝你的面试一臂之力!

3、Nginx有两类进程一类称为Master进程(相当于管理进程),另一类称为Worker进程(实际工作进程)启动方式有兩种:

(1)单进程启动:此时系统中仅有一个进程,该进程既充当Master进程的角色也充当Worker进程的角色。

(2)多进程启动:此时系统有且仅有┅个Master进程至少有一个Worker进程工作。

(3)Master进程主要进行一些全局性的初始化工作和管理Worker的工作;事件处理是在Worker中进行的

}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信