多线程与异步的区别


前言

异步是一种现象结果,多线程是实现其结果的一种手段。不可将多线程编程与异步划上等号
譬如,单线程JS语言也可通过回掉、事件驱动等操作实现异步。


提示:以下是本篇文章正文内容,首先需要明确两个概念并发与并行在继续阅读

并发:并发指在同一时间片段同时执行
并行:并行指在同一时间点同时执行

一、什么是异步

让我们来看一下百度百科对异步的解释。
在这里插入图片描述
需要注意的地方是:异步与多线程并不是同一个概念,多线程编程是实现异步的一种手段
同步异步更强调的是消息反馈机制,即调用后是否需要等待返回结果。

二、什么是多线程

多线程,是指从软件或者硬件上实现多个线程并发执行或并行执行的技术(单核CPU只可并发,多核CPU取决系统调度)。其依赖的是并发执行机制原理。

并发执行机制原理:简单地说就是把一个处理器划分为若干个短的时间片,每个时间片依次轮流地执行处理各个应用程序,由于一个时间片很短,相对于一个应用程序来说,就好像是处理器在为自己单独服务一样,从而达到多个应用程序在同时进行的效果 。
多线程就是把操作系统中的这种并发执行机制原理运用在一个程序中,把一个程序划分为若干个子任务,多个子任务并发执行,每一个任务就是一个线程。这就是多线程程序 。

利用CPU在处理其他任务时产生的空余、等待时间、压榨CPU劳动力就是多线程

三、异步与多线程异同点

  1. 异步和多线程都可以达到避免调用线程阻塞的目的
  2. 异步操作在完成await操作后,会发出完成通知,并释放占用的线程,之后系统调用线程池中空余的线程来进行await之后的操作,减少了线程负担。
  3. 而多线程编程会在整个任务中一直占用线程造成资源浪费。比如DMA(直接存储器访问)操作,允许硬件可以不通过CPU而直接与内存数据进行交互,在这时闲置的线程无法被释放,造成了资源浪费。(使用异步可以避免)

四、异步与多线程适用场景

异步:I/O密集操作
多线程:CPU密集操作

五、思考题

异步任务有三种返回类型,分别有什么区别?

  • void :执行一个任务,不需要返回值,不需要与任务进行交互;
  • Task:执行一个任务,不需要返回值,但需要与任务进行交互,可以获取任务的执行状态
  • Task<TResult>:执行一个任务,需要返回值,返回值被包含在Task的Result属性里。

下面是相同代码却使用了三次不同返回类型。大家可以思考下每种情况下的耗时是多少。

// Task<TResult>
 static async Task<int> test()
        {
             await Task.Delay(4000);
             return 1;
        }
      static void Main(string[] args)
        {   
        Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Console.WriteLine("开始");
            var task = test();
            
            Thread.Sleep(3000);
            int a = task.Result;
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
           } 

输出结果:
在这里插入图片描述
代码执行到await时,线程控制权被交还给主线程。主线程同步等待了3秒。之后获取异步操作的结果值,又等待了1秒(主线程与异步方法产生了交互)。所以最后是4秒,零头是输出等操作用时。

//Task
   static async Task test()
        {
            
                await Task.Delay(4000);
              
        }
           static void Main(string[] args)
        {   
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Console.WriteLine("开始");
            var task = test();
            
            Thread.Sleep(3000);
           
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
         }

输出结果:
在这里插入图片描述
因为主线程与异步方法没有交互了,所以在同步等待3秒后就完成了计时操作。对主线程也不会造成任何阻塞情况。
Void方法同上

      static async Task<int> test()
        {
            
                await Task.Delay(4000);
                return 1;
        }
         static void Main(string[] args)
        {   
           Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Console.WriteLine("开始");
            int a = test().Result;

            Thread.Sleep(3000);
    
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
         }

输出结果:
在这里插入图片描述
造成这个的原因是使用await 时是释放线程,线程能去执行其它任务;而Result 是让线程暂停,等待结果。所以造成了主线程阻塞。

总结

主要是为了说明异步和多线程的区别,所学有限,如有错误,望不吝指教。
下一篇介绍多线程的具体使用。线程安全、线程取消等问题

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值