[.NET]Windows线程浅谈

1.  为什么Windows要支持线程?
      早期的电脑,操作系统不提供线程的概念。整个系统就一个线程,包含了操作系统代码和应用代码。只有一个线程执行的弊端是,一个长时间运行的任务将会阻止其他所有任务执行.譬如在之前的16位windows(MS-DOS)时,一个应用在打印文档时,会导致操作系统和所有应用都停止响应. 后面微软设计操作系统时,开始给一个应用的每个实例运行一个进程.进程是单个实例使用的一系列资源集合.每个进程都有一个虚拟地址空间,确保该进程使用的代码和数据不会被另外的进程访问.
      看起来好像已经够了,但是对于CPU呢?当一个应用进入无限循环时,会怎么样?如果只有一个CPU,它会执行这个无限循环而不会执行其他任何动作,这样仍会导致系统失去响应.为了解决这个问题,就引入了线程.windows给每个进程一个特有的线程,当应用代码进入一个无限循环时,该进程对应的代码将会被冻住,但其他进程不会被冻住,他们继续运行

2.  线程的开销

        线程使得可以使用一个应用(如任务管理器)去强制杀掉(kill)另一个长时间运行的应用,但是线程也需要一些内存和执行时间性能的开销
        线程的空间和时间开销: 
            1. 线程内核对象: 操作系统在每个线程创建时都会初始化并分配这个对象,这个对象包含了描述线程的一系列属性,也包含了线程的上下文数据.上下文是一个包含一系列CPU寄存器的内存块,对于x86,x64以及ARM的CPU,线程上下文分别使用700,1240,350字节内存
            2. 线程环境块(TEB):
                TEB是在用户模式下分配的一个内存块.它占用一个页的内存(x86上是4KB).TEB包含了线程的异常处理链.进入线程的每个try入口时,会在此链的头部插入一个节点,离开try块时,则会从链上删除这个节点.另外,TEB还包含线程自己的存储数据和一些用于GDI和OpenGL图形的数据
            3. 用户模式栈: 此栈是用于本地变量和方法参数的.windows默认会给每个线程的用户模式栈分配1MB内存.
            4. 内核模式栈: 此栈是用在当应用代码需要传递参数给内核模式函数时。出于一些安全原因,当从用户模式代码传递参数到内核时,windows会复制所有这些传递的参数从线程的用户模式栈到内核模式栈,然后内核会验证参数值.内核模式栈大小是12KB(32位系统)或24KB(64位系统)
            5. DLL线程附加通知: 当一个线程在进程中创建时,所有的非托管DLL会被加装到那个进程,并调用它们的DllMain方法,传递一个DLL_THREAD_ATTACH标志.同样,在线程销毁时,也会调用此进程所有的DLL的DllMain方法,传递DLL_THREAD_DETACH标志.一些DLL可以使用这个通知来执行一些特殊的初始化或清理操作.
            早期的windows,一些进程一般就加载5到6个DLL,但是现在一些进程可能会有几百个DLL要加载,执行这个通知会比较影响性能.(注:托管程序语言产生的DLL不会有DllMain,不会接收到此通知,非托管的可通过调用Win32的DisableThreadLibraryCall函数来禁用此通知)

  2.1 线程的性能开销(线程上下文切换):
         线程的上下文切换: 一个仅有一个CPU的计算机在同一时间只能做一件事,所以windows会在所有线程上共享CPU.CPU按时间片进行切分给线程,当时间片过期时,windows上下文切换到另一个线程。每个上下文切换需要执行下面3步:
                 1. 保存CPU寄存器的值到当前运行的线程上下文(该数据在线程内核对象中)
                 2. 选择需要继续执行的下一个线程.如果此线程属于另一个进程,windows还必须切换虚拟地址空间.如果选择执行的下个线程是和之前一样是同一个线程,则不会发生上下文切换,当然也就没有性能损失
                 3. 加载选择线程的上下文数据值到CPU的寄存器
          windows大概每30毫秒执行一次上下文切换,上下文切换是一个真正的负载,它没有任何内存或性能方面的益处,只是为了给终端用户提供一个健壮的、有响应的系统.
              实际上,由于有CPU的高速缓存存在,这个上下文切换的性能也并不会很糟糕.
              此外,当执行一个GC时,CLR必须挂起所有线程(需要在所有线程上标记对象是否需要回收),所以避免多个线程可提升GC的性能.还有在调试时,一个断点命中会挂起所有线程,那么线程越多,调试也就会越慢.
              所以多线程编程时,要注意线程不是越多越好
              注: 在多个CPU的时候,windows会给每个CPU分配一个线程,windows会确保一个线程不会同时在多个CPU核上运行

comes from  CLR Via C#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值