美文网首页
进程线程、同步异步、阻塞非阻塞、并发并行

进程线程、同步异步、阻塞非阻塞、并发并行

作者: Djbfifjd | 来源:发表于2020-07-14 09:48 被阅读0次

    一、进程和线程

    1️⃣【进程Process】是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。

    进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。

    2️⃣【线程Thread】是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。

    3️⃣进程和线程的区别

    进程和线程的主要差别在于它们是操作系统不同的资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。

    4️⃣小结
    线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

    • 一个程序至少有一个进程,一个进程至少有一个线程。
    • 线程的划分尺度小于进程,使得多线程程序的并发性高。
    • 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
    • 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
    • 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

    二、同步Sync和异步Async

    1️⃣同步:所谓同步,就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或不能继续执行后续操作。简单来说,同步就是必须一件一件事做,等前一件做完了才能做下一件事。

    例如:B/S模式中的表单提交,具体过程是:客户端提交请求->等待服务器处理->处理完毕返回,在这个过程中客户端(浏览器)不能做其他事。

    2️⃣异步:异步与同步相对,当一个异步过程调用发出后,调用者在没有得到结果之前,就可以继续执行后续操作。当这个调用完成后,一般通过状态、通知和回调来通知调用者。对于异步调用,调用的返回并不受调用者控制。

    对于通知调用者的三种方式,具体如下:
    状态:即监听被调用者的状态(轮询),调用者需要每隔一定时间检查一次,效率会很低。
    通知:当被调用者执行完成后,发出通知告知调用者,无需消耗太多性能。
    回调:与通知类似,当被调用者执行完成后,会调用调用者提供的回调函数。
    例如:B/S模式中的ajax请求,具体过程是:客户端发出ajax请求->服务端处理->处理完毕执行客户端回调,在客户端(浏览器)发出请求后,仍然可以做其他的事。

    3️⃣同步和异步的区别:请求发出后,是否需要等待结果,才能继续执行其他操作。

    三、阻塞和非阻塞

    阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的。阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

    四、并发和并行

    1️⃣并发:在操作系统中,是指同一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

    当有多个线程在操作时,如果系统只有一个 CPU,则它根本不可能真正同时进行一个以上的线程,它只能把 CPU 运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。这种方式称之为并发(Concurrent)。

    2️⃣并行:当系统有一个以上 CPU 时,则线程的操作有可能非并发。当一个 CPU 执行一个线程时,另一个 CPU 可以执行另一个线程,两个线程互不抢占 CPU 资源,可以同时进行,这种方式称之为并行(Parallel)。

    3️⃣并发和并行的区别:

    你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
    你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
    你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
    并发的关键是你有处理多个任务的能力,指同一时间段运行多个程序,不一定要同时。并行的关键是你有同时处理多个任务的能力,强调的是同一个时间点并行运行,指的是同一时刻。很显然,并行要求需要多核,而并发可以单核切换运行程序,由于 cpu 的高速运转,所以看起来并发很类似并行执行,但是本质上两者是不同的。

    五、异步和多线程区别?(原理篇)

    1️⃣异步和多线程有什么区别?
    其实,异步是目的,而多线程是实现这个目的的方法。异步是说,A发起一个操作后(一般都是比较耗时的操作,如果不耗时的操作就没有必要异步了),可以继续自顾自的处理它自己的事情,不用干等着这个耗时操作返回。

    2️⃣多线程和异步操作的异同
    多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别。

    3️⃣异步操作的本质
    所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,有必要了解一下它的硬件基础。硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。

    DMA就是直接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。

    4️⃣线程的本质
    线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

    5️⃣异步操作的优缺点
    因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些 出入,而且难以调试。

    6️⃣多线程的优缺点
    多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

    异步与多线程,从辩证关系上来看,异步和多线程并不是一个同等关系,异步是目的,多线程只是我们实现异步的一个手段。什么是异步:异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回。实现异步可以采用多线程技术或则交给另外的进程来处理。

    多线程意义:

    有时程序需要在特定时间做特定的事情。比如我们有一个可见窗口的程序。该程序可能正在进行大量的后台数字运算,但是它仍然可以响应用户事件(例如单击按钮并调整其大小),这种情况可以通过异步处理来完成,异步处理将需要您的一个线程重复检查GUI工作是否间隔执行,暂停正在执行的操作以及处理GUI一段时间。许多事情都是通过这种方式完成的。

    然而,处理它的另一种可能更好的方法是使用线程。我们不需要担心该程序在逻辑运算和GUI管理之间来回切换,操作系统将为您进行管理。即使只有一个内核,您仍然可以运行多个线程,并且操作系统将尽最大努力确保所有正在运行的进程中的所有正在运行的线程都能公平分配CPU时间。

    六、理解异步,多线程和并行的区别

    没有12306的时候,大家买票只能去火车站买。因为大家都要过年回家,都还不想等,火车站只有一个,窗口只有那么多,头疼啊。更头疼的是,排到窗口的那个人,各种挑剔,不要贵的,不要晚上的,不要站票……跟售票员各种墨迹,后面的人更加着急。

    现在假设整个城市就只有1个火车,1个售票员,每个乘客咨询售票员后需要思考1分钟再决定买哪趟车的票。

    1. 异步:在买票的人咨询后,需要思考1分钟,马上靠边站,但不用重新排队,什么时候想清楚可以立马去跟售票员去买票。在该人站在旁边思考的时候,后面的人赶紧上去接着买。这时候队伍是很快的挪动的,没有阻塞,售票员的最大化的效率。

    2. 多线程:火车站开n个窗口(但还是只有一个人售票),外面同时排n个队,售票员回答咨询者问题后,立马马上去下个窗口,然后继续轮换到下个窗口…..哪个窗口的人决定好了,售票员立马过去卖给他。这个时候乘客比较简单,但万一那个队伍有人思考半天纠结,后面的人就悲剧了。

    3. 并行:复制n个火车站,同时卖票,能力大大增强。大家也可以哪个火车站人少,就去那个买票。

    可见:在只有一个火车站,且只有一个售票员的情况下,卖完一个再卖一个就会导致资源浪费,效率低下,队伍卡死,很难往前挪动。1,2优化的办法都解决了队伍不动,售票率低下的问题。但增加火车站,增加窗口,增加售票员才是好办法。

    结论:

    1. 异步和多线程其实效率差不多,但是开的窗口不多例如3个,同时有很多人都是去花5分钟,而不是1分钟去纠结的时候,多线程效率实际是低于异步的,因为售票员还是常遇到3个队伍同时卡在那纠结不能买票的时候。

    2. 这2个概念拿来对比也有点不合适,因为不是一个维度,多线程的目的还是为了实现异步,多线程应该是一种实现异步的手段。异步应该去跟同步比较才对。

    3. 多线程比较简单,但需要增设窗口,增加成本,且售票员比较累。

    4. 并行,类似同时利用多核cpu的各个核去计算。并发可分为伪并发、真并发。前者例如单核处理器的并发,后者发是指多核处理器的并发。

    5. 终极办法是并行计算,并且每个cpu下进行异步计算,这样你的每个核都充分利用。只不过对编程要求太高了太高了,如果不是密集型计算,例如大型有限元计算(多采用并发),或者服务器同时处理上千的访问(多采用异步或者多线程),还是老老实实的用传统的办法吧,毕竟常规程序的计算量对现在的硬件来说,问题都不大。

    七、理解同步阻塞、同步非阻塞、异步阻塞、异步阻塞、异步非阻塞

    同步/异步关注的是消息通知的机制,而阻塞/非阻塞关注的是程序(线程)等待消息通知时的状态。

    以小明下载文件打个比方,从这两个关注点来再次说明这两组概念,希望能够更好的促进大家的理解。

    1️⃣同步阻塞:小明一直盯着下载进度条,到 100% 的时候就完成。
    同步体现在:等待下载完成通知;
    阻塞体现在:等待下载完成通知过程中,不能做其他任务处理;

    2️⃣同步非阻塞:小明提交下载任务后就去干别的,每过一段时间就去瞄一眼进度条,看到 100% 就完成。
    同步体现在:等待下载完成通知;
    非阻塞体现在:等待下载完成通知过程中,去干别的任务了,只是时不时会瞄一眼进度条;小明必须要在两个任务间切换,关注下载进度。

    3️⃣异步阻塞:小明换了个有下载完成通知功能的软件,下载完成就“叮”一声。不过小明仍然一直等待“叮”的声音。
    异步体现在:下载完成“叮”一声通知;
    阻塞体现在:等待下载完成“叮”一声通知过程中,不能做其他任务处理;

    4️⃣异步非阻塞:仍然是那个会“叮”一声的下载软件,小明提交下载任务后就去干别的,听到“叮”的一声就知道完成了。
    异步体现在:下载完成“叮”一声通知;
    非阻塞体现在:等待下载完成“叮”一声通知过程中,去干别的任务了,只需要接收“叮”声通知即可;软件处理下载任务,小明处理其他任务,不需关注进度,只需接收软件“叮”声通知,即可。

    也就是说,同步/异步是“下载完成消息”通知的方式(机制),而阻塞/非阻塞则是在等待“下载完成消息”通知过程中的状态(能不能干其他任务),在不同的场景下,同步/异步、阻塞/非阻塞的四种组合都有应用。

    综上所述,同步和异步仅仅是关注的消息如何通知的机制,而阻塞与非阻塞关注的是等待消息通知时的状态。也就是说,同步的情况下,是由处理消息者自己去等待消息是否被触发,而异步的情况下是由触发机制来通知处理消息者,所以在异步机制中,处理消息者和触发机制之间就需要一个连接的桥梁。在小明的例子中,这个桥梁就是软件“叮”的声音。

    1️⃣同步阻塞形式:效率是最低的。
    拿上面的例子来说,就是你专心等待下载完成,什么别的事都不做。实际程序中:就是未对fd 设置O_NONBLOCK标志位的read/write 操作;

    2️⃣异步阻塞形式:异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞。
    比如select 函数,假如传入的最后一个timeout参数为NULL,那么如果所关注的事件没有一个被触发,程序就会一直阻塞在这个select 调用处。

    3️⃣同步非阻塞形式:实际上是效率低下的。
    想象一下你一边干别的事情一边还需要抬头看下载完成没有,如果把干别的事情和观察下载完成情况的位置看成是程序的两个操作的话,这个程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的。

    很多人会写阻塞的read/write 操作,但是别忘了可以对fd设置O_NONBLOCK 标志位,这样就可以将同步操作变成非阻塞的了。

    4️⃣异步非阻塞形式:效率更高。
    因为等待下载完成是等待者的事情,而通知则是电脑(消息触发机制)的事情,程序没有在两种不同的操作中来回切换。

    八、多核

    具有多个逻辑CPU内核并且可以物理上同时执行多条指令的计算机的处理器。计算机的“核心数”是计算机拥有的核心总数。计算机可能具有多个处理器,每个处理器可能具有多个核心;核心数是所有处理器上的核心总数。

    多核的优势

    多核技术具有超线程技术的所有优点并且具有更多的优势。超线程技术为每个物理内核使用两个虚拟内核来更有效地处理任务,而多内核技术则增加了物理内核。由于单个物理核心比单个虚拟核心更强大,因此双核处理器比具有超线程的单核处理器更强大。许多较新的型号CPU是超线程和多核的,从而实现了更高的性能。

    多线程和多核关系

    首先两者本质上没有必然的联系,多线程可以运行在单核上,也可以运行在多核上。一个线程可以某一时间段在一个核心上运行,下一刻在另一个核心上运行。

    线程是内核调度的最小单位。一个进程可以有多个线程,它们共同完成某个任务。线程是被包裹在进程中的,进程提供了线程运行的资源。

    进程之间互不影响,一个进程挂掉,并不影响其它进程,然而一个进程内的一个线程出现问题 ,其它线程也无法正常运行。

    九、CPU

    CPU也叫内核,是由单晶硅以一定的生产工艺制造出来的,CPU所有的计算、接受/存储命令、处理数据都由核心执行。

    CPU执行多个程序靠的是它的时钟,通过时钟中断,它可以在不同的程序之间切换,这样看上去,我们的程序就彷佛在并行执行。

    十、超线程技术

    超线程技术为CPU中存在的每个物理核心创建两个虚拟处理核心。物理核心为虚拟核心提供动力,然后虚拟核心承担任务处理的责任。每个虚拟内核都彼此相同,尽管两者都不像物理内核那么强大,但是当不启用HT时,它们合起来远远超过了物理内核的能力。这些虚拟内核的使用使CPU可以实时在内核之间委派任务。

    超线程的优点

    由CPU密集型操作(例如同时运行两个苛刻的程序)创建的工作负载(该操作会降低单个物理核心的运行速度,而不论其原始功率如何)都会在处理器的虚拟核心之间分配利用HT技术。使用两个虚拟内核同时处理任务,处理时间更短,程序打开速度更快,并且在多任务处理期间您的计算机将保持更高的响应速度。简而言之,超线程可提高处理效率。

    相关文章

      网友评论

          本文标题:进程线程、同步异步、阻塞非阻塞、并发并行

          本文链接:https://www.haomeiwen.com/subject/fvqxhktx.html