00:00
虚拟机来给大家透彻讲解一下这个县城和锁的问题。县城和所这件事儿呢,在大厂的面试之中叫做必不可少,而且呢,死人死的特别多,那俗称叫是县城与所尸横遍野是吧?嗯,关于面试题呢,我就不给大家一一的列了啊,就是其实挺多的,大家可以看看。呃,去年的时候,2019年的时候。大概我们在面大厂的时候所问用到的一些面试题,你你大概大致可以溜一遍,给大家个15秒20秒的时间。这玩意儿怎么这么卡呢,下一个客户端就不卡了啊,乖乖。乖。你曾是少年是吧?你还是那个少年?很好,我都不认识,都不认识,对了就对了,说明你有很大的成长空间。
01:06
好了,同学们。呃,这是基本上是一线大厂的一些面试题,呃,其实你弄懂这些题之后呢,那些中小厂啊,就已经应该是不在话下了,就属于是降维打击了,我呢,这个课呢,其实已经讲过好多遍了,包括去年呢,我专门讲了多炎症一高高并发大概20多个小时的课,但是从反馈来看,从大家伙的我又我又不断的讲了很多的公开课,从大家伙的反馈来看呢,很多同学理解起来还是困难。我后来就反思,我说为什么大家理解县城和所理解这个东西的时候,理解特别困难?就在于呢,有很多东西讲的特别晦涩,另外呢,很多人实际上是他底层的知识不太够,我这点也很重要。呃。所以呢,我在这个2020版的这个里面,我打算从给大家讲这个多线程的时候呢,先从程序运行的底层原理开始讲,而并不是说直接上来就给大家讲代码。
02:07
呃,我呢,今天来尝试着从这个层面来给大家讲县城和锁,以及先城、协城、管城这些东西到底是一个什么概念。现在我们就可以开始了,来准备好的同学老师扣个一,马上开始。嗯。好嘞。我先把我BT打开。呃,在我的另外一门课里头。讲的是这个计算机的底层知识。我觉得给大家讲清楚线程之前呢,需要聊给大家聊一点计算机的最基本的基底层知识,这个以前从来没给大家聊过这一点,所以有很多同学理解起来特别码特别困难,呃,我现在呢就用这个一个简单的图啊,这个图呢是来源于计算机组成原理这门课里面的一个图,大家的这个图呢,也不要执念于ARU是什么,CU是什么,Muu是什么。
03:17
先不要执念,执念于这个,先从大块上开始看,任何的一个东西呢,大家记住了,叫做先学脉络。我一直强调这一点。先学脉络,再学细节,只要你沿着这样的一个学习方法,你的效率就会提升很多很多。有很多人学习。不识庐山真面目,到庐山里头先去找庐山一棵树底下有一棵蚂蚁窝,跟那研究小蚂蚁没错,你研究蚂蚁研究的很深,但是别人问你庐山啥形状的,你根本就不知道。所以先建立知识体系,再来查漏补缺找细节。大家记住这句话。好看这里作为一台计算机来说,它最核心的组件有这么几个。
04:03
最核心,最核心的叫CPU,那么还有一个装程序的叫内存。当然还有什么硬盘啊,显示器啊,鼠标、键盘、网卡等等,这些都叫做外围设备。大家听我说。这里面程序运行你需要理解的最根本的东西,一个叫CPU,一个叫内存。在这儿呢,我想给大家简单澄清几个概念。第一个概念呢,叫做什么是程序,程序是什么东西?我呢,不想给大家讲什么那种。呃。就是特别文绉绉的那种定义化的那种语言,给大家举个例子就行,比如说你的你看到的QQ.exe比如说你看到的PowerPoint.exe像这一类的东西放到硬盘上,静静的躺在那里,这就叫一个程序。那好,对比的概念,什么叫进程?进程是什么概念?进程是什么?线程是什么?这是大厂在面多线程的时候特别特别喜欢问的一个起始的面试题,什么是进程,什么是线程?
05:08
好好,听我说所谓的进程,双击QQ.exeee1双击起来一程序。本来你看。这个QQ.exe呢,是放在我们硬盘上对吧,然后呢,我们通过浏览器能看到他一波一双击,马上起一个程序,这个程序是一个什么内容呢?实际上他把QQ.exe的一些相关的内容和资源。放到了我们的内存里面。OK,它会在内存里面分配一些资源,分配一些空间。分配好我们的什么文件的IO啊,等等等等,总而言之,这个QQ.exe双击本就跑到内存里了,占了一块空间,里面装着这个程序的指令和数据。
06:00
指令。指令是什么?就是哎,下面要执行二加三数据是什么数据,就是那二和3OK指令和数据。好一个应用程序一双击跑起来的时候,这部分的东西。这个叫一个进程。OK,所以这个进程是一个什么概念,就是程序双击开始运行之后。放到内存里的那部分内容。好了,这就叫一个进程。那么,县城又是什么呢?线程是程序执行的基本单元。好,我先说结论,如果大厂问你什么是进程,什么线程?标准的回答,进程是资源分配的基本单位,线程叫程序执行的基本单位。
07:02
啥意思?好好听我说。大家看着,依然看这张图。我们的整个的程序放到内存里之后,它有指令有代码,有指令有代码,但是这些指令未必位于同一个线程里。它会首先找。我的主线程,也就是我们的main线程。然后开始执行,执行的过程有可能有其他的执行路线,OK,这就是别的线程。好,所以进程是什么?进程是我需要一些资源,你先在内存里头帮我分配好,所以它叫做资源分配的基本单位。线程是什么?线程是我现在要执行这个程序了,OK,从main线程开始执行,然后中间可能会有分叉,可能会有合并,可能会有同步。所以线程是叫做。
08:01
我们程序执行的基本单位。好,关于这几个概念,不知道我说清楚没有。来可以继续的。同学老师扣一。嗯。好,这个这几个概念比较简单,那现在我们来看看下一个概念。这个程序怎么着才能开始运行,也就是CPU是怎么执行一个线程的。所有的人听我说,任何程序开始运行的时候。CPU执行的就是一根线程,这个线程是什么?就是main线程,Main线程开始之后才会启动其他线程开始运行。好,CPU是怎么执行一个程序的呢?CPU是这么来执行的,我们拿最简单的东西举例子啊,还是举例来说明。你仔细听,比如我有这么一条指令,叫二加三。
09:00
A等于二加三,然后你要打印这个A也好,或者怎么样也好,我们不去管它,就是我们有这么一条指令,让你算一个二加三放到A里面。A,可以理解为内存里面的一块空间,二加三就理解我们程序的数据,那这些数据呢,会被CPU通过系统的总线,哎,总而言之就是一根线,CPU和内存之间连接的一根线。读到CPU的内部里面去,CPU内部里面,我希望今天大家记住三个最基本的东西,第一个呢叫寄存器。第二个呢叫PCPC,也是一种寄存器,但是可以要把它单独给。独立出来。这个PC的全称叫program counter,叫程序计数器,无所谓,你不用管,记得它的名字是什么,你听我讲就行。我们会把这个二和这个三放到寄存器里面。放到我们CPU的寄存器里面,那么寄存器是什么意思?就是存数据用的。
10:04
所以这个二和三原来位于内存对吧,最早是位于硬盘上,被我们装到内存里,然后真正开始做二加三的计算的时候,怎么做计算呢?把二和三放到我们的寄存器里。好,由他来做计算,你可以就认为CPU里面有一个专门做计算单元,这个这个这个单元呢叫做数学逻辑单元,叫ari,这个log unit,我们不去管它叫什么名,总而言之,二和三放到寄存器里头开始运行,运行完之后的结果怎么办?返回内存给它放到A里面去,放进这个A里面五。好了,就是这么一个过程,那有同学会说,老师,这个PC是个是个啥呢?这个PC就记录一件事,记录什么事呢?下一条指令执行到哪里了,一个程序呢,就指令一,指令二,指令三,指令四。
11:00
最开始的时候,这个PC指向第一条指令,第一条指令执行完了,它就变成第二条指令,下一面就是第三条、第四条、第五条、第六条。好,我把整个的计算机的执行程序的过程大概跟大家说了一遍,这里面有好多好多细节,好多好多特别多。细到可以,你怎么样去做这个电路,怎么样去做CPU怎么样去做。这个芯片的设计,但是听我说,我还是那句话,学软件的人先把最主线的内容掌握住。我们再回顾一下,假如一个程序里面,或者说精确的说,一个线程里面要执行一个二加三,然后给它放到某一个地址上去。CPU怎么做?首先把二和三拿到我们的register里面,放到我们寄存器里。计算最后的结果,把最后结果写回到内存里。然后PC指向下一条指令,下一条指令可能是打印,可能是做另外另外一个计算。
12:04
好,这个过程。不知道我讲清楚没有。有没有同学对这块有疑问的,有疑问你直接提。没问题。给老师扣一。我知道你们会有很多很多的疑问,PC怎么知道下一条指令是哪里啊?计算器到底是怎么进行计算的呀?中间有没有缓存啊,别着急,我强调过,好好听。你呢,先建立最基本的认识,再去抠里边的细节,好吧?好,还是那句话啊,先建立最基本的认识,再去扣里面细节。ARU是计算单元,它就是用来做做计算的。嗯,先学脉络。好。我给大家讲这个东西呢,最主要要引出来一个什么什么概念呢,其实呢,嗯,CPU呢是这么一个这么一个破玩意儿,我先把笔记给大家写好啊,CPU呢是这么一个破玩意儿,它就是读。
13:06
指令。指令存哪存到PC里面对吧,然后读。数据。存到哪儿register里面,然后计算回写。然后呢,下一条指令啊,它就它就是这么一个简单的东西。他就会干一件事,所以站在CPU的角度,其实他也不知道你有多少个线程,对他来说没关系,你跟我有有半毛钱关系吗?没有,嗯。还能跟上吗?还能跟上吗?嗯。还能跟上来给老师扣个一来。PC叫做program c程序计数器,存储指定地址,你就想着,就记录着,我是执行了第一条指令了,下面又执行第二条指令了,就把这个指令的序号存在这里就可以了。
14:13
OK。没办法,现在大厂问就问底层没招,你以为我想跟你讲这些东西,我直接给你讲那个thread扭出来之后,然后run多简单,但是没办法,必须得给你讲这个。这个是DV内存模型成为计数器,可以认为这都都这都是通用的,相通的,嗯。没关系,嗯,好,我们继续啊,同学们,你们学东西的时候呢,不要想着一下子把细节全理解透彻,千万不要这么想,这个学习方式是不对的。我呢给大家讲这个底层,我主要想引出来下一个概念,就是线程是怎么进行调度的,这又是一个特别复杂内容。线程的调度,Linux里面它有一个叫线程调度器的东西,注意这里面就会牵扯到一个概念,叫做操作系统。
15:12
好,我觉得操作系统这件事儿,其实一说呢,大概就明白。我们写程序的时候,直接可以跟硬件打交道没有问题,但是你直接跟硬件打交道非常容易出错,而且会会把很容易把硬件搞死,很容易互相影响,所以在现在的计算机里头一般都是这样的,我来给大家稍微画一下。如果这个层面是我们的硬件的话。我们的CPU,我们的内存,我们的硬盘,那么在原最早开始的时候啊,我们的一个一个一个APP。一个普通的APP是完全可以直接访问硬件的,但是特别容易出错,特别容易出bug,这是最早最早最早的时候你们可能都没经历过。
16:02
后来呢,为了管理这些好多好多的APP,互相之间的竞争啊,协作呀,访问啊,他们之间的APP诞生了一个软件呢,这个软件叫做操作系统,叫operating system。呃,所有在大厂面试的时候可以这么说啊,这部分内容属于必问的操作系统,那么作为操作系统来说,他是怎么管理这些APP的呢?好好听我讲。每个APP都有好多好多好多的线程,对吧,同学们好。交到操作系统这里,操作系统会来帮你管理这些线程。什么意思,每一个APP里面。都有好多好多的县城。比方说啊,这是所有APP里面的这些个线程,我举个最简单例子。
17:01
呃,我来给他换个颜色吧。线成一,现成二,线成三,线成四,线成五啊等等等等。这些个呢,这是用户里面的APP里面的这些个线程线程料啊,有同学说老师这个我理解不了。简单听我讲,比如说我们有一个APP,这个APP是什么?这APP叫GM。JVM这个能理解吧,就是我们的hot spot,我们的Java虚拟机,大家知道我们在Java里面写一程序,New一个thread,然后让它start,就起了一个JVM里面的线程。我再强调一下啊,再说一遍,当我们一个。Java里面我们了一个thread。扭了一个,然后调了他的start,是不是我们就起了一个JVM级别的线程吗?我加过你们的线程吗?
18:05
好。听我讲,这就是。我们的APP里面所扔出来的这些线程。这些线程。Operating system对他们进行调度,调度给谁呢?主要调度给CPU。所谓的给CPU进行调度指的是什么呢?指的是。我这颗CPU。比如说。我这个CPU。该执行这个线程了。还是该执行另外一个线程了。执行多长时间好,这个东西叫做线程调度。关于这个线程调度呢,是操作系统里面比较复杂的一部分。而且前前后后经历了各种各样的算法,在Linux最新的算法呢,叫cfs,叫completely。
19:02
Fair。Schedule了啊,叫做完全公平的线程调度,这个东西呢,是我在操系统课里头讲了,但是大家基础不同,我就不不不跟你多说,我主要想强调什么呢。就是在你APP里面启动的这些个线程是需要经过操作系统。来帮你进行在CPU上进行调度的。那有同学可能就会说了,说老师你所谓的操作系统调度给CPU是一个什么概念?这个概念呢,是这样的。操作系统说下一个线程该你了。我们有一堆的程序,每个程序里面有好多个线程。操作系统来管理哪个线程扔到哪个CPU里面去执行。比如说曹旭东说下一个线程好该你了。这里有一个线程。这里有一个线程,曹俊同事,下个线程该你了,下个线程该你了,啥意思,就是你你把你的指令。
20:06
扔到PC里。把你的数据扔到register OK,然后开始进行计算,CPU它就是一个速度特别快的这么一个接待接待员,反正你来了我就接待你,我不管你是哪个线程,站在CPU角度我是看不见线程的。我只知道有人把我。
我来说两句