细说.NET 中的多线程 (一 概念)

为什么使用多线程

  1. 使用户界面能够随时相应用户输入

当某个应用程序在进行大量运算时候,为了保证应用程序能够随时相应客户的输入,这个时候我们往往需要让大量运算和相应用户输入这两个行为在不同的线程中进行。

  1. 效率原因

应用程序经常需要等待一些资源,如等待网络资源,等待io资源,等待用户输入等等。这种情况下使用多线程可以避免CPU长时间处于闲置状态。

用户态,内核态

线程内的资源有两种运行态,即用户态和内核态。某些运算可以在堆栈上进行,这种情况线程是在用户态运行的,某些需要高权限运行的指令,或者某些优先级很高的指令需要在操作系统内核中进行,这个时候线程会运行在内核态。出于安全原因,用户态和内核态的资源是不能够互相访问的,因此在用户态和内核态的切换过程中,我们需要进行相关上下文以及变量的复制,这意味的用户态和内核态的切换是以一定的时间消耗为代价的。

由于CPU是以时间片为单位进行线程的切换的,由于CPU的运算速度远大于内存的读写速度,因此CPU和内存之间通常有两级缓存,不同的线程的上下文访问的数据往往是不同的,这样线程的切换需要经常频繁的切换CPU缓存的内容,也需要更新线程的调度信息,这些都是需要花费一定的时间的,因此合理的使用多线程,来避免CPU不停的进行上下文切换。

System.Thread介绍

创建一个线程

创建每一个线程的时候,CLR都需要进行一系列的操作,如初始化线程的本地资源,为线程分配用户模式和内核模式下相应的堆栈,加载相应的托管,非托管资源等。

最简单常用的创建线程的方式是使用ThreadStart来创建线程,相关代码如下:

ThreadStart只需要一个委托即可,如果你善于使用匿名方法,也可以用匿名方法来代替委托,使用匿名方法的另一个好处是可以通过匿名方法的闭包特性来为新的线程传递参数。

虽然使用匿名方法的闭包特性可以很方便的为线程传递参数,但是也往往会带来一些不容易发现的问题,如下面的程序,由于i变量的共享,在运行的时候输出会有问题:

正确的写法应该是这样的:

线程异常的捕获

如果线程中可能需要捕获异常,那么我们不能这样做:

而是这样做:

System.Thread线程的成员

System.Threading.Thread帮助我们实现了一些线程的基本操作,如:


属性名称


说明


CurrentContext


获取线程正在其中执行的当前上下文。


CurrentThread


获取当前正在运行的线程。


ExecutionContext


获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。


IsAlive


获取一个值,该值指示当前线程的执行状态。


IsBackground


获取或设置一个值,该值指示某个线程是否为后台线程。


IsThreadPoolThread


获取一个值,该值指示线程是否属于托管线程池。


ManagedThreadId


获取当前托管线程的唯一标识符。


Name


获取或设置线程的名称。


Priority


获取或设置一个值,该值指示线程的调度优先级。


ThreadState


获取一个值,该值包含当前线程的状态。


方法名称


说明


Abort()    


终止本线程。


GetDomain()


返回当前线程正在其中运行的当前域。


GetDomainId()


返回当前线程正在其中运行的当前域Id。


Interrupt()


中断处于 WaitSleepJoin 线程状态的线程。


Join()


已重载。阻塞调用线程,直到某个线程终止时为止。


Resume()


继续运行已挂起的线程。


Start()  


执行本线程。


Suspend()


挂起当前线程,如果当前线程已属于挂起状态则此不起作用


Sleep()  


把正在运行的线程挂起一段时间。

前台线程vs后台线程

这里我们单独提一下前台线程和后台线程。在CLR中,线程分为前台线程和后台线程,当所有前台的线程执行完之后,CLR会强制结束所有正在运行的后台线程,并且不会出现任何异常。

因此你应该使用前台线程来做一些必须完成的任务,比如把流从内存中写到磁盘上。后台线程可以做一些不那么重要的事情。一旦线程对象的生命周期开始,你就不能修改IsBackground值。

由于线程是非常昂贵的资源,我们经常需要控制允许多少线程同时运行,如何控制线程的生命周期,如何管理线程,这里我们引入了线程池的概念。

细说.NET中的多线程 (二 线程池)

时间: 2024-12-25 07:52:33

细说.NET 中的多线程 (一 概念)的相关文章

细说.NET中的多线程 (六 使用MemoryBarrier,Volatile进行同步)

上一节介绍了使用信号量进行同步,本节主要介绍一些非阻塞同步的方法.本节主要介绍MemoryBarrier,volatile,Interlocked. MemoryBarriers 本文简单的介绍一下这两个概念,假设下面的代码: using System; class Foo { int _answer; bool _complete; void A() { _answer = 123; _complete = true; } void B() { if (_complete) Console.W

细说.NET中的多线程 (二 线程池)

上一章我们了解到,由于线程的创建,销毁都是需要耗费大量资源和时间的,开发者应该非常节约的使用线程资源.最好的办法是使用线程池,线程池能够避免当前进行中大量的线程导致操作系统不停的进行线程切换,当线程数量到达了我们设置的上限,线程会自动排队等待,当线程资源可用时,队列中的线程任务会依次执行,如果没有排队等候的资源,线程会变为闲置状态. 使用ThreadPool来访问线程池 这种做法可以让我们不用那么复杂的去实现创建,重用线程的逻辑,但是也有一些限制,比如由他内置的方法,我们不知道什么时候线程池里面

细说.NET中的多线程 (五 使用信号量进行同步)

上一节主要介绍了使用锁进行同步,本节主要介绍使用信号量进行同步 使用EventWaitHandle信号量进行同步 EventWaitHandle主要用于实现信号灯机制.信号灯主要用于通知等待的线程.主要有两种实现:AutoResetEvent和ManualResetEvent. AutoResetEvent AutoResetEvent从字面上理解是一个自动重置的时间.举个例子,假设有很多人等在门外,AutoResetEvent更像一个十字旋转门,每一次只允许一个人进入,进入之后门仍然是关闭状态

NET 中的多线程

NET 中的多线程 为什么使用多线程 使用户界面能够随时相应用户输入 当某个应用程序在进行大量运算时候,为了保证应用程序能够随时相应客户的输入,这个时候我们往往需要让大量运算和相应用户输入这两个行为在不同的线程中进行. 效率原因 应用程序经常需要等待一些资源,如等待网络资源,等待io资源,等待用户输入等等.这种情况下使用多线程可以避免CPU长时间处于闲置状态. 用户态,内核态 线程内的资源有两种运行态,即用户态和内核态.某些运算可以在堆栈上进行,这种情况线程是在用户态运行的,某些需要高权限运行的

iOS开发笔记--iOS中的多线程

摘要 本文主要介绍iOS开发中的三种多线程技术:NSThread, NSOperation/NSOperationQueue, GCD.以及在多线程编程中的注意点和小技巧. 多线程 NSThread NSOperation/NSOperationQueue GCD 目录[-] iOS中的多线程 iOS的三种多线程技术特点: GCD基本思想 队列: 操作: 不同队列中嵌套同步操作dispatch_sync的结果: 同步操作dispatch_sync的应用场景: GCD优点: GCD队列: NSOp

Java中的多线程你只要看这一篇就够了

Java中的多线程你只要看这一篇就够了 引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其实只有一半对,因为反应"多角色"的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的"生产者,消费者模型". 很多人都对其中的一些概念不够明确,如同步.并发等等,让我

VC中利用多线程技术实现线程之间的通信

文章来源:[url]http://www.programfan.com/article/showarticle.asp?id=2951[/url] 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.

多线程的概念

多线程的概念 一.程序与进程 1.程序:一段静态的代码. 2.进程:程序的一次动态执行过程,它对应从代码加载.执行到执行完毕的一个完整过程. 3.进程也称任务,支持多个进程同时执行的OS就被称为多进程OS或多任务OS. 二.进程与线程 在一个程序内部也可以实现多个任务并发执行,其中每个任务称为线程. 线程是比进程更小的执行单位,它是在一个进程中独立的控制流,即程序内部的控制流. 特点:线程不能独立运行,必须依赖于进程,在进程中运行. 每个程序至少有一个线程称为主线程. 单线程:只有一条线程的进程

iOS中的多线程及GCD

多线程中的一些概念 //任务:代码段  方法  线程就是执行这些任务 //NSThread类 创建线程 执行线程 [NSThread isMainThread]//判断是否是主线程 #import "AppDelegate.h" @implementation AppDelegate -(void)dealloc { [_window release]; [super dealloc]; } - (BOOL)application:(UIApplication *)applicatio