论并行,并发,同步,异步之间的联系与区别

Posted SaoJian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了论并行,并发,同步,异步之间的联系与区别相关的知识,希望对你有一定的参考价值。

前言

前段时间和一些网友大佬讨论异步,并发之类专业名词的区别,具体的实现,收获颇多,于是决定写下这篇博客作记录。

下面我们将其两两分类进行讨论。

并行/并发(Parallelism/Concurrency)

这里借用GPT搜索的回答

并行:并行是指在同一时刻执行多个操作。并行通常需要多个线程或进程来实现。

并发:并发是指在一段时间内执行多个操作。并发操作通常是由单个线程或进程中实现的,荣国时间片轮转等机制来实现多个操作的交替。

 如图所示。

并行是通过多核cpu的核心,创建多个线程,同时间执行多个任务。

并发是通过将cpu单个核心的使用按时间片来划分,交替给不同的任务执行,以达到同事执行多个任务的目的。

他们的相同点是,并行与并发都是为了提高系统吞吐量,响应速度,可靠性,提升cpu利用率而提出的技术。

在c#中可以使用Thread类创建线程来达到并行。

// 创建一个新线程
using System.Diagnostics;
Thread t1 = new Thread(new ThreadStart(DoWork));
// 创建一个新线程
Thread t2 = new Thread(new ThreadStart(DoWork));
Console.WriteLine(Process.GetCurrentProcess().Threads.Count);//输出当前运行的线程数
// 启动线程
t1.Start();
Console.WriteLine(Process.GetCurrentProcess().Threads.Count);//输出当前运行的线程数
t2.Start();
Console.WriteLine(Process.GetCurrentProcess().Threads.Count);//输出当前运行的线程数
// 等待线程结束
t1.Join();
t2.Join();
Console.WriteLine("Main thread exiting.");
static void DoWork()

    Console.WriteLine("Worker thread started.");

    Thread.Sleep(2000);//模拟线程要执行的任务耗时2秒

    Console.WriteLine("Worker thread exiting.");

同步/异步(Synchronous/Asynchronous)

同样是借用GPT搜索的回答

同步:同步是指在执行某个操作时,必须等待该操作完成后才能继续执行下一个操作。同步操作通常是阻塞的,即在执行操作期间,程序会一直等待,知道操作完成为止。

异步:异步是指在执行某个操作时,不必等待该操作完成就可以继续执行下一步操作。异步操作通常是非阻塞的,即在执行操作其间,程序可以继续执行其他操作。

上面两句话其实非常好理解,我们借用微软官方文档做早餐的例子。假设一个人做早餐需要三步,第一步准备餐具,耗时五分钟,第二步煮咖啡,耗时十分钟,第三步烤面包,耗时十分钟。

在同步的模式下,由于线程是阻塞的,我们必须等待上一步操作完成才能继续下一步操作,那么我们的做早餐的步骤为准备餐具->煮咖啡->烤面包,总共耗时二十五分钟。

而我们知道,在现实生活中,准备完餐具之后,煮咖啡和烤面包两件事是可以同事进行的。

此时便是异步的模式,因为不会阻塞线程,程序运行至异步方法时会直接返回进行下一步操作,那么我们做早餐的步骤为准备餐具->煮咖啡,同时烤面包,总共耗时十五分钟。

在c#中,主要使用async await关键字及Task类来进行异步编程

同步代码:

var datetime1= new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();//获取当前时间戳
await PrepareTableware();//准备餐具
await MakeCoffee();//煮咖啡
await Toast();//烤面包
var datetime2= new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
Console.WriteLine("任务总耗时(单位秒):"+(datetime2-datetime1));

//准备餐具
async Task PrepareTableware()

    var obj = 1000;
    await Task.Delay(obj);//模拟准备餐具耗时


//煮咖啡
async Task MakeCoffee()

    var obj = 2000;
    await Task.Delay(obj);//模拟煮咖啡耗时


//烤面包
async Task Toast()

    var obj = 2000;
    await Task.Delay(obj);//模拟烤面包耗时

 异步代码:

var datetime1= new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();//获取当前时间戳
await PrepareTableware();//准备餐具
 var task1=MakeCoffee();//煮咖啡
 var task2=Toast();//烤面包
await Task.WhenAll(task1,task2);
var datetime2= new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
Console.WriteLine("任务总耗时(单位秒):"+(datetime2-datetime1));

//准备餐具
async Task PrepareTableware()

    var obj = 1000;
    await Task.Delay(obj);//模拟准备餐具耗时


//煮咖啡
async Task MakeCoffee()

    var obj = 2000;
    await Task.Delay(obj);//模拟煮咖啡耗时


//烤面包
async Task Toast()

    var obj = 2000;
    await Task.Delay(obj);//模拟烤面包耗时

 后话

在实际的业务开发过程中,数据库查询,文件上下传,远程请求等场景,使用异步编程能有效的提高CPU利用率,提高程序的性能。

使用并行编程,即多线程编程,尤其需要注意线程安全问题,否则一旦线程死锁,程序就会崩溃。

以上便是个人对与同步,异步,并发,并行等概念一些粗浅的理解,如果有错误,欢迎大家指出。

 

并发 并行 同步 异步 多线程 阻塞 非阻塞的区别

  1. 并发(concurrency):在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。其中两种并发关系分别是同步和互斥

    • 互斥:进程间相互排斥的使用临界资源的现象,就叫互斥。

    • 同步(synchronous):进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待。具有同步关系的一组并发进程相互发送的信息称为消息或事件。

    • 其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并发是指多核处理器的并发。

  2. 并行(parallelism):在单处理器中多道程序设计系统中,进程被交替执行,表现出一种并发的外部特种;

    在多处理器系统中,进程不仅可以交替执行,而且可以重叠执行。在多处理器上的程序才可实现并行处理。

    从而可知,并行是针对多处理器而言的。并行是同时发生的多个并发事件,具有并发的含义,但并发不一定并行,也亦是说并发事件之间不一定要同一时刻发生。

  3. 多线程:多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码。多线程可以实现线程间的切换执行。

  4. 异步(asynchronous):异步和同步是相对的,同步就是顺序执行,执行完一个再执行下一个,需要等待、协调运行。异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。线程就是实现异步的一个方式。异步是让调用方法的主线程不需要同步等待另一线程的完成,从而可以让主线程干其它的事情。

?? 异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。实现异步可以采用多线程技术或则交给另外的进程来处理。

5.? 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。

6.? 非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

?

同步与异步是对应的,它们是线程之间的关系,两个线程之间要么是同步的,要么是异步的。
阻塞与非阻塞是对同一个线程来说的,在某个时刻,线程要么处于阻塞,要么处于非阻塞。
阻塞是使用同步机制的结果,非阻塞则是使用异步机制的结果。

===============================================================================================
为了对以上概念的更好理解举一个简单例子,??假设我要做 烧开水,举杠铃100下, 洗衣服 3件事情。

烧开水 这件事情,??我要做的事情为, 准备烧开水 1分钟, 等开水烧开 8 分钟 , 关掉烧水机 1分钟
举杠铃100下? ?? ???我要做的事情为,??举杠铃100下??10分钟
洗衣服? ?? ?? ?? ?我要做的事情为, 准备洗衣服 1分钟, 等开水烧开 5 分钟 , 关掉洗衣机 1分钟

单核情况下
同步的完成,我需要做的时间为 1+ 8 +1 + 10 + 1+ 5 +1 = 27 分

如果异步,就是在等的时候,我可以切换去做别的事情

准备烧开水(1) + 准备洗衣服(1) + 举50下杠铃 (5)分钟+ 关洗衣机 1分钟 + 举杠铃20下 (2)分钟+ 关烧水机 1分钟 + 举30下杠铃(3)分钟
1+1+5+1+2+1+3 =14 分钟

双核 异步 并行

核1??准备烧开水 1分钟+ 举杠铃50下(5)分钟+ 等待3分钟 + 关掉烧水机 1分钟

核2??准备洗衣服 1分钟+ 举杠铃50下(5)分钟+ 关掉洗衣机 1分钟 + 等待3分钟

其实只花了 1+5+3+1 = 10分钟

其中还有双核都等待了3分钟

双核 异步 非并行

核1??举杠铃100下(10)分钟

核2??准备烧开水 1分钟+ 准备洗衣服 1分钟+ 等待5 分钟+ + 关掉烧水机 1分钟??+ 等待 1 分钟 + 关掉洗衣机 1分钟

其实只花了 1+5+3+1 = 10分钟

多线程的做法
单核下

线程1??准备烧开水 1分钟, 等开水烧开 8 分钟 , 关掉烧水机 1分钟
线程2??举杠铃100下??10分钟
线程3??准备洗衣服 1分钟, 等开水烧开 5 分钟 , 关掉洗衣机 1分钟

cpu 可能这么切换 最理想的切换方式

线程1??准备烧开水1??sleep??1? ?? ?? ? sleep 5? ?? ?? ?? ?sleep 1? ?? ?? ? sleep 2? ?? ?? ? 关开水 1分钟 exit
线程2? ? sleep 1? ?? ?sleep??1? ?? ?? ?? ?举杠铃50 5分钟? ? sleep 1? ?? ?? ? 举杠铃20 2分钟??sleep1? ?? ?举杠铃30下 3分钟? ?? ?
线程3? ? sleep??1? ?? ?准备洗衣服1 分钟? ? sleep 5? ?? ?? ?? ?关洗衣机1分钟? ? exit

最后使用了??14分钟??和异步是一样的。
但是实际上是不一样的,因为线程不会按照我们设想的去跑, 如果线程2 举杠铃先跑,整个流程的速度就下来了。

异步和同步的区别,??在io等待的时候,同步不会切走,浪费了时间。

如果都是独占cpu 的业务, 比如举杠铃的业务, 在单核情况下 多线和单线 没有区别。

多线程的好处,比较容易的实现了 异步切换的思想, 因为异步的程序很难写的。多线程本身程还是以同步完成,但是应该说
比效率是比不上异步的。 而且多线很容易写, 相对效率也高。

多核的好处,就是可以同时做事情, 这个和单核完全不一样的。


转载: 小地盘

----------------------------------------仅供于学习 如有侵权 请联系删除-----------------------------------------

以上是关于论并行,并发,同步,异步之间的联系与区别的主要内容,如果未能解决你的问题,请参考以下文章

并发,并行,同步,异步的区别

并发 并行 同步 异步 多线程的区别

并发 互斥 并行 同步 异步 多线程的区别

并发 并行 同步 异步 多线程 阻塞 非阻塞的区别

并行,并发,串行,同步,异步,阻塞,非阻塞,同步阻塞,同步非阻塞,异步阻塞,异步非阻塞

并发与同步异步的概念