明天过后歌词,圣痕炼金士01,艾戴尔
操作系统创建线程是有代价的,其主要开销在下面列举出来了。
线程内核对象
拥有线程描述属性与线程上下文,线程上下文占用的内存空间为 x86 架构 占用 700 字节、x64 架构 1240 字节 、arm 架构 350 字节。
线程环境块(teb)
teb 消耗一个内存页,占用 4kb内存。
用户模式栈。
用户模式栈存储传递给方法的局部变量与实参,并且还存储有一个地址用于当前方法返回的时候,线程应该从哪个地方继续执行。默认 windows 分配保留 1mb 内存。
内核模式栈。
32 位 windows 占用 12 kb,64 位 windows 占用 24 kb。
dll 线程连接与线程分离通知。
这种策略只有 windows 才会存在,当创建线程时, windows 会调用进程所有非托管 dll 的 dllmain 方法,并未其传递 dll_thread_attach 标志,线程终止时传递 dll_thread_detach 标志。
windows 在任何时刻都只会将 1 个线程分配给 1 个 cpu ,该线程享有一个时间片的运行时间。时间片到期之后,windows 会将上下文切换到另外一个线程,动作如下:
以上操作做完之后,windows 等待这个线程时间片到期,执行下次切换,每次切换的时间开销大概为 30 毫秒。
如果一个线程时间片结束之后,下一个调度的线程还是之前的线程则不会产生线程上下文切换。
所以在理想状态下,每个系统最佳的线程数应该与其核心数相同,(如果是 4 核 8 线程则最优应该为 8 个)因为这样上下文切换出现的情况就会少很多。
最重要的是,windows 系统上大部分程序线程都处于空闲状态,但是线程占用的内存空间是事实存在的。
一般来说不推荐使用 thread 手动创建线程,而应该使用线程池,不过在有以下需求时,可以手动创建线程。
在调用过程中,如果使用了 thread.join()
方法那么就会造成调用线程阻塞当前代码,直到创建的线程被终止。
作者的观点是,计算机的 cpu 使用率应该保持 100% 的使用率才不算是浪费计算资源。
抢占式系统通过优先级来判定线程在什么时候调度多少时间,每个线程都分配了从 0 到 31 的优先级,系统为 cpu 分配线程时,首先检查 31 的线程,并以轮询的方式调度他们(优先级都为 31)。
如果高优先级的线程一直处于调度状态,那么操作系统不会将 cpu 分配给低优先级的线程,这样就会造成 线程饥饿。
较高的优先级线程总会抢占低优先级线程,即便该线程的时间片没有用完。
cpu 会创建一个优先级为 0 的 零页线程 ,该线程是系统唯一一个优先级为 0 的线程,只有在 cpu 空闲的时候会执行他,用于清理 ram 中所有的空闲内存页。
【注意】
进程优先级类 + 线程优先级构成了一个基础优先级,windows 还有一个动态优先级用于防止产生线程饥饿,会动态调成线程的优先级状态。
但是动态优先级只会针对基础优先级在 0 ~ 15 的线程应用,16 ~ 31 不受这个管控。
windows 通过两个抽象层用于表示进程优先级类和线程优先级,单一般 c# 用户代码中能够控制的只有线程优先级,他们分别是:lowest、belownormal、normal、abovenormal、highest。
在 clr 中线程只有两种状态,前台线程和后台线程,而且当所有前台线程被终止之后,clr 会强行关闭所有后台线程,并退出程序。
线程在运行的生命周期当中可以变更其状态,但主线程默认为前台线程,使用 thread 类型创建的线程默认也是前台线程。只有线程池的线程默认为后台线程,进入托管执行的本机代码创建的任何线程也会标记为后台线程。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
asp.net搭建博客,使用BlogEngine.NET+MySql搭建博客
网友评论