C#线程

进程和线程

进程是一个系统级别的概念,用来描述一组资源和程序运行所必须的内存分配。每一个进程都有一个唯一的进程标识符(PID);线程是进程的基本单元;进程的入口点创建的第一个线程被称为主线程;线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。

应用程序域(AppDomain):.Net可执行程序承载在进程中的逻辑分区;一个进程可以包含多个应用程序域,每一个应用程序域中承载一个.Net可执行程序;每一个程序域都和该进程(或其它进程)中的其它的程序域完全彻底隔离开,只有使用分布式编程协议(如WCF)才能访问其它应用程序域中的任何数据;

System.AppDomain

一个线程可以穿梭在多个应用程序域中,但在某个时刻,线程只会处于一个应用程序域内。

上下文边界

每个线程都有自己的属性,在每个线程的内核对象之中,都包含一个上下文结构,上下文结构的存在是为了反映在线程上一次执行时,线程CPU寄存器的状态。在任何时刻,Windows只将一个线程代码分配给一个CPU,一个线程允许运行一个时间片,在线程的“时间片”结束之后,Windows会检查现有所有线程内核对象,只有那些没有在等待什么的线程才适合调度。Windows选择一个可调度的线程内核对象,并且换到它。

Windows选择一个可调度的线程有一套独特的标准,Windows执行线程的规律和时间片没多大的关系,线程在运行的任何时刻都可以停止,然后Windows又去调度另一个线程,你有点控制权,去控制你想运行的线程,但是这控制权不多,不控制为好。对于线程的执行,记住一点:

你不能保证自己的线程一直运行,你不能阻止其他的线程的运行。

线程优先级别0~31,Windows把线程用从高到低的调度方式轮流调度线程,假如有一个优先级别为31的线程运行结束了,然后Windows会找下一个空闲的线程,如果空闲的线程中有一个级别也是31的线程,那么Windows又会把31级别的线程交给CPU处理。

进程优先级类:

Windows支持6个进程优先级类:Idel,Below Normal,Normal,Above Normal,Hight和Realtime(依次向高),其中Normal是默认的进程优先级,所以它是最常用的。

Windows支持7个相对线程优先级:Idel,Lowest,Below Normal,Normal,Above Normal,Highest和Time-Critical。


相对线程优先级


进程优先级


Idle


Below Normal


Normal


Above Normal


High


Realtime


Time-critical


15


15


15


15


15


31


Highest


6


8


10


12


15


26


Above Normal


5


7


9


11


14


25


Normal


4


6


8


10


13


24


Below Normal


3


5


7


9


12


23


Lowest


2


4


6


8


11


22


Idle


1


1


1


1


1


16

记住:如果更改一个进程的优先级类,线程的相对优先级不会改变,但它的优先值会改变

Windows永远都不会调度进程,他调度的只有线程,“进程优先级类”是Microsoft提出的一个抽象概念,目的是为了帮助你理解自己的应用程序和其他正在运行的应用程序的关系,它没有别的用途。

可以更改它的线程相对优先级,Thread中的Priority属性,向它传递ThreadPriority枚举类型中定义的5各值之一,即在上表中的灰色部分列。

线程池ThreadPool

每个进程都有一个线程池,线程池的默认大小为:每个可用的处理器有 25 个线程。使用 SetMaxThreads 方法可以更改线程池中的线程数。

ThreadPool类型拥有一个QueueUserWorkItem的静态方法。该静态方法接收一个委托(WaitCallback),代表用户自定义的一个异步操作。

//     一个 System.Threading.WaitCallback,表示要执行的方法。

//     如果此方法成功排队,则为 true;如果未能将该工作项排队,则引发 System.NotSupportedException。

//System.NotSupportedException:承载公共语言运行时的宿主不支持此操作。

[SecuritySafeCritical]

public static bool QueueUserWorkItem(WaitCallback callBack);        // 将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。

//     System.Threading.WaitCallback,它表示要执行的方法。

//   state:   包含方法所用数据的对象。

//     如果此方法成功排队,则为 true;如果未能将该工作项排队,则引发 System.NotSupportedException。

[SecuritySafeCritical]

public static bool QueueUserWorkItem(WaitCallback callBack, object state);

使用线程池的好处:

减少了线程的创建、开始和停止的次数,提高了效率

能够使我们将注意力放在业务逻辑上而不是多线程架构上。

以下场景是不适合使用线程池,而是手工管理线程:

  1. 需要前台线程时。因为线程池中的线程总是后台线程。
  2. 需要线程具有特定的优先级。因为放到线程池中的线程都是默认的优先级(ThreadPriority.Normal),无法对其优先级进行设置。
  3. 需要长时间运行的任务。由于线程池具有最大线程数限制,因此大量阻塞的线程池线程可能会阻止任务启动。
  4. 如果需要有一个带有固定标识的线程便于退出、挂起或通过名字发现它。
  5. 对于COM对象,入池的所有线程都是多线程单元(multithreaded apartment MTA)线程;许多COM对象都需要单线程单元(single-threaded apartment STA)线程;
时间: 2024-12-21 02:21:58

C#线程的相关文章

各科基础详实

一. Java基础部分 1. JAVA的基本数据类型有哪些 ?  String 是不是基本数据类型 ? 2. 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 3. Java有没有goto? 7 4. 说说&和&&的区别. 7 5. 在JAVA中如何跳出当前的多重嵌套循环? 7 6. switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 8 7. short s1 = 1; s1 = s1 + 1;有什么

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); 1 2 3 4 5 6 7 new Thread(new

201709018工作日记--线程状态的转换

先来张图: 线程在一定条件下,状态会发生变化: 1.新建状态(New):新创建了一个线程对象 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权. 3.运行状态(Running):就绪状态的线程获取了CPU,执行程序代码. 4.阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行.直到线程进入就绪状态,才有机会转到运行状态.阻塞的情况分三种:   (一).等

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

线程的控制和线程池

一.WaitHandle: ”.Net 中提供了一些线程间更自由通讯的工具,他们提供了通过"信号"进行通讯的机制 可以通过ManualResetEvent,AutoResetEvent(他是在开门并且一个 WaitOne 通过后自动关门)来进行线程间的通讯 waitOne:    等待开门 Set:           开门 Reset:       关门 static void Main(string[] args) { ManualResetEvent mre = new Manu

内存池、进程池、线程池

首先介绍一个概念"池化技术 ".池化技术 一言以蔽之就是:提前保存大量的资源,以备不时之需以及重复使用. 池化技术应用广泛,如内存池,线程池,连接池等等.内存池相关的内容,建议看看Apache.Nginx等开源web服务器的内存池实现. 起因:由于在实际应用当中,分配内存.创建进程.线程都会设计到一些系统调用,系统调用需要导致程序从用户态切换到内核态,是非常耗时的操作.           因此,当程序中需要频繁的进行内存申请释放,进程.线程创建销毁等操作时,通常会使用内存池.进程池.

线程高级

例题,哲学家用餐: 在一张餐桌上坐着五个哲学家,但是却只有五根筷子,每个哲学家只有一根筷子,所以当一个哲学家要夹菜的时候需要用他旁边那个哲学家的筷子,被拿走筷子的哲学家则只能等待那个哲学家吃完放下筷子他才能夹菜. 示意图:  设计思路: 首先编写一个筷子类,每根筷子都是一个对象,这个类里有拿起.放下两个方法:当一个哲学家线程来调用拿起方法时,下一个哲学家线程就要进入等待状态,然后这个哲学家线程调用放下方法后,就激活那个等待中的哲学家线程,以此循环,轮流使用筷子. 代码示例:  接着设计哲学家类,

缓冲池,线程池,连接池

SSH:[email protected]:unbelievableme/object-pool.git   HTTPS:https://github.com/unbelievableme/object-pool.git 缓冲池 设计要点:包含三个队列:空缓冲队列(emq),装满输入数据的输入的队列(inq),装满输出数据的输出队列(outq),输入程序包括收容输入(hin),提取输入(sin),输出程序包括收容输出(hout)和提取输出(sout). 注意点:输入程序和输出程序会对缓冲区并发访

能够在子线程绘画的View SurfaceView

转载请注明出处:王亟亟的大牛之路 近期两天都没有写文章,一方面是自己在看书.一方面不知道写什么,本来昨天想写Glide或者RxAndroid的东西结果公司的"狗屎"网怎么都刷不好Gradle我也是无语了(FQ也没用).准备今天背着笔记本 回家搞.真是服了.. 抱怨的话不说了,来看下这一篇要讲的主角 SurfaceView,关于SurfaceView的文章事实上在别的一些网站上也有,由于我之前没写过,所以也就一直没整这部分的内容(别人写的好坏反正找好的点自己吸收吧,嘿嘿) 问题:Surf

java线程安全问题之静态变量、实例变量、局部变量

Java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如:"一个类在可以被多个线程安全调用时就是线程安全的". 此处不赘述了,首先给出静态变量.实例变量.局部变量在多线程环境下的线程安全问题结论,然后用示例验证,请大家擦亮眼睛,有错必究,否则误人子弟! 静态变量:线程非安全. 静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态