您的位置:首页 > 其它

多线程技术

2019-06-21 21:40 225 查看

多线程技术

目录

正文内容:

一、计算机线程

二、怎么看待线程开销问题

三、多线程实现形式

四、多线程的代码分析阶段

五、线程在内存空间上的开销

六、线程在时间上的开销

七、线程池

 

 

正文内容:

一、计算机线程

1、计算机的线程如图:

2、计算机中的线程: 任务管理器中事四核八线程(逻辑处理器),意味着能同时执行8个任务。任务管理器中有1472个线程,但是绝大部分都在休眠,但不管怎么休眠,线程数还是远远超过8个(实际线程数)

3、进程:运行一个程序就会有一个进程,一个进程又会有很多个线程

4、CPU资源分配方法:资源分配其实是按照线程分配(分配过程忽略),计算机及执行的时候,也会考虑到进程的优先级问题,计算机执行的时候,也会考虑到优先级问题,优先级受操作系统控制,一般不收开发者控制,因为如果开发者能随意更改优先级,将会产生很多流氓软件

5、当实际线程数多于CPU逻辑处理器时,时如何执行这些线程的呢?引入时间片的概念。采用时分复用技术,码分多址技术和频分多址技术等。时分复用技术,以1秒为单位,1时间片大概30毫秒,就等于1秒约等于33片,假如有9个线程,分别以几个时间片的单位执行,执行完时间片切换到下一个线程,如图线程和占用时间片(33个时间片9个线程),每个线程分配的时间片不同,

 

1111 1111 11111 1111 11111 111 111 11 111 .....
线程1 线程2 线程3 线程4 线程5 线程6 线程7 线程8 线程9 其他线程


线程是以串行执行,切换速度很快

6、多线 程技术使得程序的并行执行(从微观上实际是并发)成为可能。例如,一个线程播放音乐,另一个线程下载文件,它们可以“同时”使用CPU和内存等资源,彼此却没有因此而受到影响(从用户角度看)

二、怎么看待线程开销问题

1、我们通常写的程序都是同步的,如果我们想主动增加线程,就必须独立开启

2、开启一个线程,时间上和空间上都需要开销

3、开发中我们不能过多的开启线程,否者性能不仅不会提高反而会下降

三、多线程实现形式

1、异步编程:

  • 最早在.NET 1.0时代,可以基于异步编程,就是可以同时多个任务(并行执行)
  • 异步编程是基于委托实现的,现在用的很少
  • 其主要核心是invoke方法和回调函数
  • 因为功能弱,编写麻烦,有其他简单的可供选择,所以用的很少

 

2、Thread线程:简化了异步编程编写方法,但因为时间和空间的开销较大,并且垃圾回收机制GC也不是很快捷,同样使用的少。thread方式 需要一个就得我们自己 new一个

3、ThreadPool线程池:顾名思义,提前准备好,想用就拿过来用,用完放回去就行  

4、需求如表:有A B C D E五个线程

Thread和ThreadPool不能解决的情况
A-->B-->C-->D-->E 顺序执行
(A,B,C,D)-->E ABCD全部执行完后再执行E
(A,B,C,D)-->E ABCD中任意一个完成就执行E
A-->B-->C(error)-->D-->E 当C发现错误,可以取消整个任务链
。。。。。。。。。。 。。。。。。。。。。。。。

5、Task: Thread和ThreadPool虽然可以使用,有的 7ff7 时候还很不错,但是功能不能满足我们的需求,所以出现了Task,Task可以说是Thread和ThreadPool的结合,但不是简单结合,在性能上,资源开销上,都得到很好的优化,在.NET4.0以后,不管大小微软都建议使用Task

6、其他的并行编程,如parallel等。。。。

四、多线程的代码分析阶段

1、为了搞懂原理,建议使用windbg,windbg是一个能够观察程序底层的工具,尤其是线程等

2、windbg的使用(本机路径):

使用步骤:

  • 首先找到clr.dll和sos.dll,VS安装目录——》Windows——》Microsoft.NET——》framework64——》V 4.0 30319——clr.dll和sos.dll
  • 然后将clr.dll和sos.dll复制到windbg安装目录中,启动windbg.exe并配置windbg工具,附加一个进程,加载.clr.dll和sos.dll后(.loadby clr sos)完成剩下操作,注意要运行的是debug中的要测试线程的.exe文件才行

windbg看看的内容:

  • windbg命令:.loadby clr sos——加载clr和sos模块;!threads——查看所有线程;!ThreadState 线程号——查看线程状态
  • 线程终结器(MTA(Finalizer)):主要作用就是回收线程,起作用跟回收站类似,线程不用先到线程终结器中,还可以回复,不想恢复的话最后会被GC清理
  • 系统线程:主线程

 

 

3、前台线程和后台线程的区别:

  • 前台线程:如果一个程序有前台线程,必须在所有前台进程都结束后才能推出程序
  • 后台线程:如果一个程序开启的都是后台线程,那么在退出程序后,后台线程也就会全部退出

 

4、应用程序域:

  • 一个应用程序对应一个进程,每个进程都会映射物理内存,从而隔离程序,进程是隔离的
  • 问题引入:计算机在执行不同进程的同时,会跨进程,耗费时间
  • 需求:希望一个进程中能使用另一个程序,但又不想单独用进程启动,因为进程开销大,根据问题和需求.NET引入应用程序域(appDomain)的概念,并且将它设置在进程和线程之间
  • 每一个进程至少会包括一个应用程序域。在托管代码运行时,CLR还会额外创建系统域共享域存放所有应用程序都需要的资料

5、线程的声明周期:thread生命周期中各个实例方法,开始、暂停、继续、中断和重新开始;和thread相关的静态方法,数据槽、本地数据 存储等

 

线程在内存空间上的开销

1、Thread内核数据结构:

  • 主要有OSID(线程的ID)和contex上下文(存放CPU寄存器相关的变量)
  • 理解:CPU切换任务时,会保存相关数据以备下次使用,(寄存器就是主要的存储)

 

2、查看当前环境块(!teb):(Thread Environment Block)线程环境块,下图参数就是内存的开销,都会占用资源,所以要研究

3、用户模式堆栈:

  • 用户程序的“局部变量”和“参数传递”所使用的堆栈
  • 常见的某些循环中出现溢出StackOverFlowException,一般都是死循环,一个线程分配1MB的堆栈空间,主要是参数、局部变量

 

4、内核模式堆栈:程序最后,还得调用底层的Win32函数,用户模式的参数必须还得传递过来,这部分肯定还会占用空间

 

六、线程在时间上的开销

 

1、资源使用通知开销:从Modeload列表中,就能看出资源加载必须要通知的

!dumpdomain查看 应用程序域,有三部分系统域(system domain)、共享域(shared domain)和私有域domain1,应用程序自己的)

2、时间片切换开销:切换线程开销也很大

七、线程池

 

 

1、Thread:也就是一个任务,开启一个thread需要时间,并且threaddied的时候,在一定时间内也会 占用资源

2、threadPool线程池:由系统完成并缓存,默认都已经初始化完毕,并且没有死线程。可以随时拿来用,用完随时放回去

发现:没有死线程,并且线程数只有4个,因为有4个逻辑处理单元,理论开启4个线程。也可以设置线程个数,不建议自己设置

3、thread和threadpool总结:当我们使用thread的时候,创建10个线程,就会有10个独立的线程运行,浪费时间和空间。但是,当我们使用threadpool的时候,解决10个独立线程能完成的任务。随着CPU核心的增加,这个线程池的个数也会增加,性能也会增加。独立线程个数减少,开销也会减少

4、虽然threadpool可以使用,但是满足不了一些特俗要求,所以有了Task,Task是threadpool和thread结合后功能的进一步增强

异步开启方式:

Task.start()方法

Task.Run()方法

Task.Factory.StartNew()方法

同步开启方式

 

 

 

 

 

 

 

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: