首页 > 其他分享 >个人在学习过程中对多线程和异步的理解

个人在学习过程中对多线程和异步的理解

时间:2024-02-25 21:58:58浏览次数:28  
标签:异步 Console Thread Method 理解 线程 多线程 Id

私人对于异步与多线程的理解

前言

​ 异步与多线程都是并发问题的一种解决方式,但是异步是程序员层面,线程是操作系统层面的。

​ 其次,异步与线程解决并发问题的实现方式和目的是不同的。下面举一个不太贴切的例子。如果把线程当作一条单行道,那么多线程就是通过扩展多条道路从而实现多车辆(方法、程序)的通行。而异步则是忽略车辆的物理体积,一条路(单线程)可以同时有多辆车通过,不会出现堵车(线程阻塞)情况,谁的速度快谁就跑在前面。

​ 如果是不忽略车辆的物理体积,那么多线程只是解决异步问题的一种手段,但是单线程仍然可以进行异步操作。下面的代码可以更好的理解异步和线程的区别:

例子

​ 我们定义了三个异步任务,在每个异步任务中,我们要求在任务开始执行的时候在控制台打印出线程ID,然后通过延时一秒钟来模拟做点事情,最后,我们依然要求控制台打印出线程ID。

public static async Task FirstAsync()
{
    Console.WriteLine("First Async Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
    await Task.Delay(1000);
    Console.WriteLine("First Async Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}

public static async Task SecondAsync()
{
    Console.WriteLine("Second Async Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
    await Task.Delay(1000);
    Console.WriteLine("Second Async Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}

public static async Task ThirdAsync()
{
    Console.WriteLine("Third Async Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
    await Task.Delay(1000);
    Console.WriteLine("Third Async Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}

​ 现在,我们添加另一个异步方法来执行上面的异步方法

public static async Task ExecuteAsyncFunctions()
{
    var firstAsync = FirstAsync();
    var secondAsync = SecondAsync();
    var thirdAsync = ThirdAsync();

    await Task.WhenAll(firstAsync, secondAsync, thirdAsync);
}

​ 最后我们使用main方法来使得整个示例运行:

static async Task Main(string[] args)
{      
    await ExecuteAsyncFunctions();
}

​ 运行的结果如下:

First Async Method on Thread with Id: 1
Second Async Method on Thread with Id: 1
Third Async Method on Thread with Id: 1
Third Async Method Continuation on Thread with Id: 4
Second Async Method Continuation on Thread with Id: 8
First Async Method Continuation on Thread with Id: 11

​ 我们可以看到刚开始,所有三个异步任务都是在线程ID为1上面运行的,但是经过1秒钟的睡眠,当再次执行异步任务的时候,每个任务又被别的线程执行起来。在这里显示为4,8和11。

​ 为什么会发生这样的事情呢?原因就在于当线程发现关键字await的时候,该线程就会从当前逻辑释放而返回给线程池。一旦睡眠结束,一个新的线程(4,8,11)就重新被分配来执行三个任务。

​ 同样地,我们再看看多线程的代码示例,与上面的例子不同,我们去除了关键字async

public class Multithreading
{
    public void FirstMethod()
    {
        Console.WriteLine("First Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(1000);
        Console.WriteLine("First Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
    }

    public void SecondMethod()
    {
        Console.WriteLine("Second Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(1000);
        Console.WriteLine("Second Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
    }

    public void ThirdMethod()
    {
        Console.WriteLine("Third Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(1000);
        Console.WriteLine("Third Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
    }
}

​ 逻辑和之前一样,都是打印线程ID睡眠然后再打印线程ID。同样地,我们创建一个方法,在这个方法里,起三个线程来启动三个任务。最后用main函数运行应用。

public void ExecuteMultithreading()
{
    Thread t1 = new Thread(new ThreadStart(FirstMethod));
    Thread t2 = new Thread(new ThreadStart(SecondMethod));
    Thread t3 = new Thread(new ThreadStart(ThirdMethod));

    t1.Start();
    t2.Start();
    t3.Start();
}

​ main函数

static async Task Main(string[] args)
{      
    Multithreading multithreading = new Multithreading();
    multithreading.ExecuteMultithreading();
}

​ 运行的结果如下:

First Multithreading Method on Thread with Id: 14
Second Multithreading Method on Thread with Id: 15
Third Multithreading Method on Thread with Id: 16
Second Multithreading Method Continuation on Thread with Id: 15
First Multithreading Method Continuation on Thread with Id: 14
Third Multithreading Method Continuation on Thread with Id: 16

​ 如果我们对比一下异步的例子,就可以得出明显的区别。在多线程的例子里,我们显式地分配了线程,该线程直到做完对应的任务才会结束,即使逻辑当中有一段时间的休眠。

总结

​ 异步编程和多线程编程的区别在于侧重点不同,两者对于提高可用性和性能方面起到了关键性的作用。

参考

https://zhuanlan.zhihu.com/p/570792890

标签:异步,Console,Thread,Method,理解,线程,多线程,Id
From: https://www.cnblogs.com/keepingstudying/p/18033142

相关文章

  • C# 理解Thread.Sleep()方法
    C#理解Thread.Sleep()方法转载:https://www.cnblogs.com/nzbbody/archive/2012/03/06/2381359.html我们可能经常会用到Thread.Sleep函数来使线程挂起一段时间。那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题:1、假设现在是2008-4-712:00:00.000,如果我调用一下......
  • IOC简单理解
    IOCrefreshBeanFactory()0、实例化IOC容器(就是一个Map<String,BeanDefinition>)1、资源加载器加载解析配置文件资源加载器接口ResourceLoader资源的抽象和访问接口ResourceFileSystemResource,文件系统资源的实现类ClassPathResource,classpath下资源的实现类UrlReso......
  • 通俗理解微服务
    微服务是什么?-阮一峰的网络日志(ruanyifeng.com)......
  • 异步FIFO设计
    同步FIFOREVIEW方法1:使用计数器判断空满方法2:使用扩展一位的地址指示空满,读写指针最高位不同,剩余的位都相同,表示满了;读写指针相等,表示空异步FIFO格雷码产生gray_code=data^(data>>1)相邻两个数之间只有一个bit发生变化异步FIFO原理读写时钟不一致使用......
  • 函数探秘:深入理解C语言函数,实现高效模块化编程
    ✨✨欢迎大家来到贝蒂大讲堂✨✨......
  • C#使用Channel实现异步任务之间的通信
    channel中也是有一个ConcurrentQueue来维护的usingSystem.Threading.Channels;varchannel=Channel.CreateUnbounded<Message>();//在赋值的时候,两个Task就开始执行了,下面的await就是为了等待执行完成varsender1=SendMessageAsync(channel.Writer,1);varsender2=......
  • volatile及内存屏障理解总结
    volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些未知的因素更改。volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存......
  • 【Spring】spring事件监听异步处理
    在Spring框架中,ApplicationEventMulticaster接口是用于发布事件的核心组件。要支持异步处理事件,可以通过配置一个能够执行异步任务的TaskExecutor与SimpleApplicationEventMulticaster配合使用。以下是一个配置示例:importorg.springframework.context.annotation.Bean;importo......
  • 循环掌控:深入理解C语言循环结构,高效实现重复性任务
    ✨✨欢迎大家来到贝蒂大讲堂✨✨......
  • 如何理解:人工智能才是真正的新能源
    今天看到这段话:你以为的新能源:电力驱动真正的新能源:人工智能​​​SamAltman在英特尔的活动上也提到了这一点,如果非要类比,把现在当做交流直流大战的阶段是个恰当的比喻。在电力技术初期,人们对于电力的本质、产生方式以及它如何转化和利用其他自然资源有很多探索和质疑......