1、进程-线程-多线程,同步和异步的概念
我们生活中有许许多多关于进程与线程的小例子,比如:1.我们使用打开一个微信软件,这个时候就开启了一个进程,当我们在微信里面进行各种操作(查看朋友圈,扫一扫…),这么多的操作就是线程。
所以我们可以说”进程”是包含”线程”的,”线程”是”进程”的一个子集。
进程(Process) 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 在当代面向线程设计的计算机结构中,进程是线程的容器。
程序是指令、数据及其组织形式的描述,进程是程序的实体。是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
** 线程(thread)**是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
简单总结一下:
**
**
进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。
线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。(程序执行流的最小单位)
**
**
进程与线程的理解:
1.计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。
2.假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。
3.进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。
4.一个车间里,可以有很多工人。他们协同完成一个任务。
5.线程就好比车间里的工人。一个进程可以包括多个线程。
6.车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。
7.可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。
8.一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫“互斥锁”(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。
9.还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。
10.这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做“信号量”(Semaphore),用来保证多个线程不会互相冲突。
不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。
11.
操作系统的设计,因此可以归结为三点:
(1)以多进程形式,允许多个任务同时运行;
(2)以多线程形式,允许单个任务分成不同的部分运行;
(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。
计算机的概念
01、进程与线程
进程和线程是计算机的概念。
进程:一个程序运行时,占用的所有计算资源的总和。
线程:程序执行流的最小单位;任何操作都是由线程完成的;
线程依托于进程存在的,一个进程可以包含多个线程;
线程也可以有自己的计算资源。
02、多线程
1. 多个执行流同时进行。
CPU太快了,分时间片。(上下文切换)
微观角度,一个核同一时刻只能执行一个线程;宏观角度,多线程并发执行。
2.多CPU多核 可以独立工作,并发进行。
6核12线程(6个物理核,12个虚拟核。这里的“线程”代表的是虚拟核)
3.Tread类是C#语言对线程对象的封装。
计算机方面的多线程和开发Tread,Task、TreadPool、Parallel中的多线程不完全一样。
并发执行机制原理:
简单地说就是把一个处理器划分为若干个短的时间片,每个时间片依次轮流地执行处理各个应用程序,由于一个时间片很短,相对于一个应用程序来说,就好像是处理器在为自己单独服务一样,从而达到多个应用程序在同时进行的效果。
03、同步/异步
同步/异步是对方法执行的描述。
同步:完成计算后,再进入下一行。按顺序执行。
异步:不会等待方法的完成,会直接进入下一行。无需等待执行。非阻塞。
1 | action.Invoke(name); |
04、异步、多线程
认识:C#异步、多线程。多线程就是多个Tread并发;C#语言里面的东西。
线程是源于操作系统的。
理解:同步方法卡界面(主UI线程,忙于计算)
异步多线程方法不卡界面,主线程完事儿了,计算任务交给子线程在做。
异步多线程作用
1、可以提升用户体验。(Winform,还可以使用主UI线程)
2、一个业务操作后发送邮件。(web开发,异步发送邮件。无需等待)异步+回调?异步多线程和Ajax区别?
3、速度快。用资源换时间(可能出现资源不够的情况)
4、多线程有管理成本。
5、多个独立任务可以同时进行的情况下,才有使用价值!
6、启动无序、执行时间不确定。结束也无序。
注意:尽量避免通过等几毫秒的形式来控制启动/执行时间/结束。//Tread.Sleep(5); 顺序控制不好控制!
回调 / 状态检测 / 状态等待 / 信号量??
Action和Func 委托的异步调用
AsyncCallback 异步回调函数
1 | private void btnAsyncAdvanced_Click(object sender, EventArgs e) |
1 | private void btnAsyncAdvanced_Click(object sender, EventArgs e) |
![IMAGE](resources/8D23A3B21044A753826A7426C65D5ECC.png =1440x365)
1 | asyncResult0.AsyncWaitHandle.WaitOne();//等待任务的完成,及时等待 |
1 | action.EndInvoke(asyncResult0);//可以等待 |
1 | private void btnAsyncAdvanced_Click(object sender, EventArgs e) |
![IMAGE](resources/7A1C7A4EA248C639D2051E728AF58B1E.png =1098x343)
附:如何将类封装起来,提供成一个dll?
多线程
Tread、TreadPool、Task、Parallel
1、Tread 线程
.Net 1.0 时代
01、线程的开启、挂起、唤醒、销毁、取消销毁
1 | Action action = () => this.DoSomethingLong("btnThreads_Click");//无参数无返回值的委托 |
1 | try |
02、线程等待
1 | //线程等待 |
1 | while (thread.ThreadState != ThreadState.Stopped) |
03、前台线程和后台线程
1 | Console.WriteLine(thread.IsBackground);//默认是flase。 前台线程,启动之后一定要完成任务的,阻止进程退出。 |
04、线程的优先级
1 | thread.Priority = ThreadPriority.Highest;//线程优先级 CPU优先执行Highest |
2、ThreadPool 线程池
.Net 2.0 时代
线程池——享元模式——数据库连接池
01、Thread提供了太多的API,大部分意义不大。容易误伤… …
02、会无限使用线程,加以限制。
03、重用线程,避免重复的创建和销毁!准备容器Pool,减少创建和销毁的开销。
01、线程池启动多线程
1 | Console.WriteLine($"****************btnThreadPool_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); |
02、线程池的最大线程数、最小线程数
1 | ThreadPool.SetMaxThreads(16, 16); |
1 | { |
03、ThreadPool 线程等待
ManualResetEvent 手动重置事件。其他Api基本取消了。
1 | //类 包含了一个bool属性 |
但是一般来说,不要阻塞线程池的线程。
1 | for (int i = 0; i < 20; i++) |
04、线程池的重用
1 | ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btnThreadPool_Click")); |
1 | private void DoSomethingLong(string name) |
![IMAGE](resources/CB9A1F9BF5EC5814354988EB340CAFDE.png =1376x411)
05、线程的回调
**
**
** 基于Thread线程的回调**
1 | //启动子线程计算--完成委托后,该线程去执行后续回调委托 |
1 | this.ThreadWithCallback(() => Console.WriteLine($"这里是action {Thread.CurrentThread.ManagedThreadId.ToString("000")}"), |
1 | //带返回的异步调用,需要获取返回值。 |
1 | Func<int> func = this.ThreadWithReturn<int>(() => |
![IMAGE](resources/EA398D4B7796B6DB35E9050768E64CC7.png =975x106)
- 本文作者: 梁俊可
- 本文链接: http://ljk3d.com/2021/10/19/cSharpNote/CSharp高级进阶教程_12_异步和多线程(委托的异步使用)/
- 版权声明: 梁俊可工作室