zoukankan      html  css  js  c++  java
  • 《CLR via C#》之线程处理——线程基础

    《CLR via C#》之线程处理——线程基础

    windows为什么要支持线程

    早期的操作系统只有一个执行线程,但同时包含了操作系统代码和应用程序代码,一旦应用程序出现bug,整个主机必须重启,数据都会丢失。
    微软后来发布了新的内核——Windows NT。决定在一个进程中运行应用程序的实例。进程实际是应用程序实例需要使用的资源的集合。保护了数据的安全性。但是如果发生死循环呢?如果机器只有一个CPU,他会执行死循环,虽然数据不会被破坏,系统依然会停止响应。微软的解决方案就是线程。它的职责是对CPU进行了虚拟化。每个进程都有专用的线程(相当于一个CPU)。

    线程开销

    和一切虚拟化机制一样,线程有空间(内存耗用)和时间(运行时的执行性能)上的开销:

    • 线程内核对象(thread kernel object)
      为每个线程分配的数据结构之一。包括描述线程的一组属性,线程上下文(CPU寄存器集合)。x86,x64,ARM CPU架构,上下文分别占约700,1240,350字节。
    • 线程环境块(thread environment block, TEB)
      TEB是用户模式中分配和初始化的内存块,占用一个内存页(三种架构都是4kB)。
    • 用户模式栈(user-model stack)
      存储传给方法的局部变量和实参。Windows默认分配1MB内存(保留地址空间,需要时换到物理内存。
    • 内核模式栈(kernel-model stack)
      用于向OS内核模式函数传递实参。Win32:12KB;Win 64:24KB。
    • DLL线程连接(attach)和线程分离(detach)通知
      Windows的一个策略是,任何进程在创建和终止线程时,都会调用进程加载的所有非托管DLL的DLLMain方法。

    上下文切换开销
    Windows大约每30ms执行一次上下文切换。这个动作不会带来任何内存或性能上的收益。事实上,上下文切换可能带来其它的性能损失,比如缺页中断,cache写入。
    执行GC时,CLR必须挂起所有线程,遍历它们的栈查找根以便对堆中的对象进行标记(GC算法第一步),再次遍历它们的栈(更新它们的根),再恢复所有线程。所以减少线程的数量会显著提升GC的性能。
    线程越多,调试体验越差(遇到断点时挂起所有线程)。


    CPU发展趋势

    除了提高CPU的速度外,还有多核——为了使用线程。
    目前的三种多CPU技术:

    • 多个CPU;
    • 超线程CPU——芯片中包含两组架构状态,比如CPU寄存器,但只要一组执行资源;
    • 多核CPU。

    CLR线程和Windows线程

    目前,CLR线程完全等价于Windows线程。


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

    应尽量使用线程池来执行异步的计算操作。但是如果满足以下任何条件,就可显式创建自己的线程。

    • 线程需要非Normal的优先级运行。
    • 需要线程是一个前台线程,防止应用程序在线程结束前终止。
    • 直接为长时间运行的任务创建专用线程。因为,线程池为了判断是否需要创建一个额外的线程,所采用的逻辑比较复杂。
    • 需要控制线程(启动,并可能调用Abort方法)。

    线程调度和优先级

    Windows是抢占式多线程操作系统,所有你不能保证自己的线程一直运行,也阻止不了其它线程的运行。
    Microsoft知道开发人员 在为线程分配优先级时很难做到完全合理,因此公开了优先级系统的一个抽象层。

    • 进程优先级类(抽象概念):决定应用程序与其它应用相比的响应能力。
      6个进程优先级类:Idle,Below NormalNormal(默认),Above NormalHigh(绝对必要时使用),和Realtime(尽量避免使用)。
    • 优先级:线程优先级
      Windows支持7个相对线程优先级:IdleLowestBelow NormalNormalAbove NormalHighestTime-Critical

    每个线程的优先级取决于两个标准:1)它的进程优先级类;2)在其进程优先级类中,线程的优先级。他俩合并构成一个线程的“基础优先级”。每个线程都有一个“动态优先级”,线程调度器根据 这个优先级决定执行哪个线程。最初,基础优先级和动态优先级相同。系统可以提升基础优先级在0到15之间的线程优先级(即,概念上非Realtime优先级类)。

    事实上,Windows永远不会调度进程,它只调度线程。

    C#可以通过设置Thread的Property属性,来设置相对线程优先级。ThreadPriority枚举:Lowest,BelowNormal,Normal,AboveNormal或者Highest。和Windows为自己保留了优先级0和Realtime范围一样,CLR为自己保留了Idle和Time-Critical优先级。





  • 相关阅读:
    动态规划之 0-1背包问题及改进
    动态规划之矩阵连乘
    python3 入门 (四) 类与继承
    动态规划之最长公共子序列(LCS)
    java并发包分析之———AQS框架
    java并发包分析之———BlockingQueue
    java并发包分析之———Deque和LinkedBlockingDeque
    java并发包分析之———concurrentHashMap
    java并发包分析之———ConcurrentSkipListMap
    java并发包分析之———Atomic类型
  • 原文地址:https://www.cnblogs.com/qianzi067/p/5808344.html
Copyright © 2011-2022 走看看