进程:操作系统分配的占有CPU资源的最小单位。拥有独立的地址空间。
线程:安排CPU执行的最小单位。同一个进程下的所有线程,共享进程的地址空间。
简单讲,计算机就像工厂,进程是个大车间,计算机内部有很多个这样的大车间。线程是工人,每一个车间里的工人至少有一个。
为什么这么画呢?有点一个挨一个的效果呢?是因为以前我就老是疑惑进程或者线程运行时到底是并行?还是串行?
其实,在单CPU或单核的情况下,宏观上无论是进程也好,线程也罢,都是并行的。而在微观下,某一个具体的时刻,他们实际上都是串行的。在多CPU或多核的情况下,才是真正意义的并行。
二、线程和进程的关系、通性
关系:进程中包含着至少一个线程。在进程创建之初,就会包含一个线程,这个线程会根据需要,调用系统库函数去创建其他线程。但需要注意的是,这些线程之间是没有层级关系的,他们之间协同完成工作。在整个进程完成工作之后,其中的线程会被销毁,释放资源。
通性:都包含三个状态,就绪、阻塞、运行。通俗的讲,阻塞就是资源未到位,等待资源中。就绪,就是资源到位了,但是CPU未到位,还在运行其他。
三、线程的好处
既然,线程和进程是存在通性的,那么为什么操作系统还要设置线程这个单位,那就说说线程的几点好处:
1、在一个程序中,多个线程可以同步或者互斥并行完成工作,简化了编程模型;
2、线程较进程来讲,更轻;
3、线程虽然微观并行。但是,在一个进程内部,一个线程阻塞后,会执行这个进程内部的其他线程,而不是整体阻塞。从某种意义上,提高了CPU的利用率。
四、市面上的通用叫法
单线程与多线程,都指在一个进程内的单和多。不要笑我,之前真的不懂。心中那只小羊驼,奔过来,跑过去。还抬起了傲娇的眼睛,看了我一眼,呵呵~~~
五、javaScript单线程执行机制
1、 首先解释下,单线程和多线程。
什么是单线程?单线程就是一个进程中只有一个线程。程序顺序执行,前面的执行完,才会执行后面的程序。
什么是多线程?多线程就是一个进程中只有多个线程。在进程内部进行线程间的切换,由于每个线程执行的时间片很短,所以在感觉上是并行的。
2、那么为什么感觉上javaScript是多线程?而且还支持AJAX异步呢?AJAX是真正的异步吗?
先说明,从哪里可以得出javaScript是单线程。比如你页面一上来就alert(“hello world~”);只要你不关闭这个对话框,后续的js代码就不会再执行。因为,单线程就是这样一步一步的顺次执行,前面不执行完,后面不会执行。也就是说,在具体的某一时刻,只有一段代码在执行。
可是,JavaScript明明可以处理各种触发事件,感觉上是异步多线程啊。其实,它的原理是这样的,JavaScript单线程的执行浏览器的一个事件队列,要执行的函数和触发事件的回调函数都被放在这个队列中。比如,我点击率一下按钮,之后又将浏览器缩小了,那么这两个事件的回调函数就会顺次地被放在当前执行的“函数”之后,再一一执行。
那么,既然JavaScript是单线程,那么如何维护这个函数队列呢,他分身无术啊。这时候,就需要知道,浏览器可不是单线程。虽然,每一个window只有一个js引擎,但是浏览器是事件驱动的、异步的、多线程的。
浏览器内部有一个事件轮询(event loop),是一个大的内部消息循环,会轮询大的消息队列,并执行。也就是js要处理的事件队列,是浏览器维护的。
浏览器至少有四个线程(不同浏览器会有差异): js引擎线程、界面渲染线程、浏览器事件触发线程、http请求线程。
其实,到这里就说的很明白了。但是,又想到了延时函数(setTimeout)的例子,感觉上,因为没有阻塞执行,会感觉是异步,其实并不是。只是,js在执行到延时函数时,会触发浏览器的定时器,到设置时间,浏览器再将这个函数放入执行的函数队列,再由JavaScript引擎执行。都是在浏览器空闲了才会执行。
关于AJAX的异步,是真正的异步。同样的道理,在调用AJAX的时候,浏览器会开辟一个新的线程,去处理这个请求,得到响应后,如果这个请求有回调,会将这个回调再放入事件队列中。再由JavaScript引擎执行。
3、关于JavaScript的阻塞
浏览器虽然是多线程,但是由于JavaScript具有阻塞特性,无论外链还是内嵌脚本,在浏览器执行解释js脚本的时候,浏览器是不会去做别的事情的,比如渲染页面,而是直到js下载并执行完毕。
这样,js脚本的下载、解释执行,会反该页面的继续绘制,给用户带来不良的体验。所以,要对其优化,有如下几点:
a、将<script>内嵌和外链,在可以的情况下,放在<body>底部。注:对于css,浏览器是并行下载
b、在页面onload后,加载js
c、html5 <script>标签的defer属性,在页面加载完成后下载
d、使用创建<script>标签的方式,在页面加载完成后添加进去。
注:解决阻塞就是一句话,先让页面渲染完,再加载js。
六、Node.js单线程执行机制
脑子就像有问题一样。js都是单线程的了,node.js就是js实现的,还能是多线程?!!呵呵哒~
Node.js其实还不是真正意义上的js,他是借用了js语法实现的,达到真正意义的非阻塞服务端语言。但是他的运行机制,也是事件轮询 (Event Loop)。
GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中,等到JS引擎空闲时,立即被执行。
tip: 关于debugger的阻塞
以上内容纯属瞎编,各位看官请谨慎
我觉得会。我的一些理解:
页面呈现过程是:
1、取回html代码,从上往下进行解析。
2、解析我觉得就是构建dom树和render树以及renderlayer树,前面是html各节点的结构树,后两棵用于渲染页面。构建dom树我理解为,比如说我遇到<html>就构建一个html节点,后面遇到<body>我就把html视为父亲节点,节点存放指向body。一直遇到</html>代表后面没有了子节点。
3、如果构建dom树过程中遇到了script、img或者css就加载进来,我用chrome的时候,发现这些资源是并行加载的,就是发送请求的时间一样。(这里就有个小问题想请教,如果构建dom树是从上往下的话,应该遇到这些标签时间应该有先后,那么chrome是怎么实现的并行额?)
4、dom树构建和render树构建renderlayer树构建是同时进行的,第3点说到遇到script就加载,加载完后会马上执行,所以dom树后续节点并不能构建,这里就会发生运行阻塞了。
注:js单线程的相关知识说js引擎和渲染不是同一线程,这里跟js阻塞渲染不矛盾,因为dom树构建到script标签时候,后续节点被阻塞构建,但是可能render树和renderlayer树还在构建(前面的节点),这两树构建(实际上dom树构建我怀疑也在渲染线程里面)属于渲染线程。所以这时就是js在运行,渲染在工作,符合两线程的特点。