一、线程开销

操作系统创建线程是有代价的,其主要开销在下面列举出来了。

内存开销

  1. 线程内核对象

    拥有线程描述属性与线程上下文,线程上下文占用的内存空间为 x86 架构 占用 700 字节、x64 架构 1240 字节 、ARM 架构 350 字节。

  2. 线程环境块(TEB)

    TEB 消耗一个内存页,占用 4KB内存。

  3. 用户模式栈。

    用户模式栈存储传递给方法的局部变量与实参,并且还存储有一个地址用于当前方法返回的时候,线程应该从哪个地方继续执行。默认 Windows 分配保留 1MB 内存。

  4. 内核模式栈。

    32 位 Windows 占用 12 KB,64 位 Windows 占用 24 KB。

  5. DLL 线程连接与线程分离通知。

    这种策略只有 Windows 才会存在,当创建线程时, Windows 会调用进程所有非托管 DLL 的 DllMain 方法,并未其传递 DLL_THREAD_ATTACH 标志,线程终止时传递 DLL_THREAD_DETACH 标志。

线程上下文切换与 CPU 之间的关系

Windows 在任何时刻都只会将 1 个线程分配给 1 个 CPU ,该线程享有一个时间片的运行时间。时间片到期之后,Windows 会将上下文切换到另外一个线程,动作如下:

  1. 将 CPU 寄存器值存储在当前正在运行的线程的内核对象内部的上下文结构之中。
  2. 从先有线程集合选取一个线程供调度,如果该线程属于另一个进程,还得切换 CPU 能够操作的虚拟地址空间。
  3. 将上下文结构中的值加载到 CPU 寄存器之中。

以上操作做完之后,Windows 等待这个线程时间片到期,执行下次切换,每次切换的时间开销大概为 30 毫秒。

如果一个线程时间片结束之后,下一个调度的线程还是之前的线程则不会产生线程上下文切换。

所以在理想状态下,每个系统最佳的线程数应该与其核心数相同,(如果是 4 核 8 线程则最优应该为 8 个)因为这样上下文切换出现的情况就会少很多。

最重要的是,Windows 系统上大部分程序线程都处于空闲状态,但是线程占用的内存空间是事实存在的。

三、使用专用线程执行计算限制的异步操作

一般来说不推荐使用 Thread 手动创建线程,而应该使用线程池,不过在有以下需求时,可以手动创建线程。

  1. 需要设定更高的线程优先级的时候。
  2. 需要将线程设置为前台线程。
  3. 某些长耗时的专用线程。
  4. 该线程可能会通过 Thread 的 Abort 方法终止自身。

在调用过程中,如果使用了 Thread.Join() 方法那么就会造成调用线程阻塞当前代码,直到创建的线程被终止。

四、为什么要使用线程

  1. 针对于客户端程序而言,多线程可以增强响应性,不会因为耗时操作阻塞 UI 线程造成用户体验卡顿。
  2. 针对于服务器程序而言,可以并发地处理用户请求,充分利用多核 CPU 的优势。

作者的观点是,计算机的 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 类型创建的线程默认也是前台线程。只有线程池的线程默认为后台线程,进入托管执行的本机代码创建的任何线程也会标记为后台线程。

《CLR Via C#》读书笔记:26.线程基础的更多相关文章

  1. CLR via C# 读书笔记-26.线程基础

    前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...

  2. 《CLR via C#》读书笔记 之 线程基础

    第二十五章 线程基础 2014-06-28 25.1 Windows为什么要支持线程 25.2 线程开销 25.3 停止疯狂 25.6 CLR线程和Windows线程 25.7 使用专用线程执行异步的 ...

  3. [Clr via C#读书笔记]Cp4类型基础

    Cp4类型基础 Object类型 Object是所有类型的基类,有Equals,GetHashCode,ToString,GetType四个公共方法,其中GetHashCode,ToString可以o ...

  4. 《Windows核心编程》读书笔记.Chapter06线程基础

    原文链接在印象笔记(效果也好的多):https://app.yinxiang.com/l/AAQlNLnxTPRMAppVr5W0upchipQDDC_FHlU 概要: 现成也有两个组成部分: 现成的 ...

  5. CLR Via CSharp读书笔记(26) - 计算限制的异步操作

    执行上下文: 执行上下文包括安全设置(压缩栈.Thread的Principal属性和Windows身份),宿主设置(System.Threading.HostExecutionContextManag ...

  6. (CLR via C#学习笔记)异步操作 - 线程池

    一 线程池基础 1.线程池维护了一个操作请求队列,将请求的操作追加到线程池队列中,线程池的代码从队列中提取操作项,派发给线程池中的线程; 2.CLR初始化时,线程池中是没有线程的,当有操作派发给线程池 ...

  7. CLR via C# 读书笔记-21.托管堆和垃圾回收

    前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...

  8. Java并发读书笔记:线程安全与互斥同步

    目录 导致线程不安全的原因 什么是线程安全 不可变 绝对线程安全 相对线程安全 线程兼容 线程对立 互斥同步实现线程安全 synchronized内置锁 锁即对象 是否要释放锁 实现原理 啥是重进入? ...

  9. Clr Via C#读书笔记---I/O限制的异步操作

    widows如何执行I/O操作      构造调用一个FileStream对象打开一个磁盘文件-----FileStream.Read方法从文件中读取数据(此时线程从托管代码转为本地/用户模式代码)- ...

随机推荐

  1. Windows Server 2012 配置远程桌面帐户允许多用户同时登录

    网上找了很多关于设置远程桌面最大连接数的文章,大都是说先要到控制面板的管理工具中设置远程桌面会话主机等,大体和我之前的文章<设置WINDOWS SERVER 2008修改远程桌面连接数>里 ...

  2. mysql几种关联的区别

    1.平时都是用的逗号的模式:select * from a,b where a.id=b.id,逗号的模式等于inner join和join: 2.left join 和 right join相反,效 ...

  3. IE 11和const的兼容问题

    说好的IE11兼容javascript中的常量类型 const 呢 ?可能并没有完全兼容 项目中遇到一个问题,采用google浏览器访问没问题,在本地jetty启动,IE11也可以正常访问,然而当我将 ...

  4. 用STS构建spring boot

    操作步骤:1. 登录地址http://spring.io/tools 下载sts,spring-tool-suite-3.9.5.RELEASE-e4.8.0-win32-x86_64.zip2. 解 ...

  5. 【翻译】Flume 1.8.0 User Guide(用户指南) Processors

    翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...

  6. bond绑定两张物理网卡为一张逻辑网卡

    问题:cnetos7同时接入两个独立网络,但两个网络的IP网段相同时只能路由到一个网络 解决方法:使用bond绑定两张物理网卡为一张逻辑网卡 1.新建文件bond.conf,内容如下 alias bo ...

  7. mysql thread pool

    转自:http://blog.csdn.net/wyzxg/article/details/8258033 mysql 线程处理流程图: Mysql支持单线程和多线程两种连接线程模式,如果单线程,则在 ...

  8. vs 2017 打开 iis express问题

    问题: 更新vs2017 15.6.4后,首次打开网站 iis express 一直报 无法连接到web服务器. 解决办法: 关闭防火墙,在次启动即可,启动成功后,在次打开防火墙也无影响.

  9. mysql中加入海量数据

    delimiter // create procedure m() begin declare num int; set num=1; while num < 100000 insert int ...

  10. Oracle简单查询实例

    --查询不重复的职位 select distinct job from emp; --查询年薪,起别名,别名不要用单引号括起来 as nianxin from emp sal; --以这样的形式显示具 ...