admin 管理员组

文章数量: 1086019


2024年7月7日发(作者:动态登录页面代码)

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行

的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序

计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资

源. 线程也可以称为轻型进程 (Light Weight Process,LWP)。

它是一种非常"节俭"的多任务操作方式。在Linux系统下,启动一个新的进程必须分

配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一

种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的

地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的

空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。当然,在

具体的系统上,这个数据可能会有较大的区别;

什么是线程?

每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能

是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,

它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量

级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。

什么是多线程?

多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率。线程是

在同一时间需要完成多项任务的时候被实现的。

多线程 - 好处

使用线程的好处有以下几点:

·使用线程可以把占据长时间的程序中的任务放到后台去处理

·用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可

以弹出一个进度条来显示处理的进度

·程序的运行速度可能加快

·在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较游泳

了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

还有其他很多使用多线程的好处,这里就不一一说明了。

一些线程模型的背景

我们可以重点讨论一下在Win32环境中常用的一些模型。

·单线程模型

在这种线程模型中,一个进程中只能有一个线程,剩下的进程必须等待当前的线程执

行完。这种模型的缺点在于系统完成一个很小的任务都必须占用很长的时间。

·块线程模型(单线程多块模型STA)

这种模型里,一个程序里可能会包含多个执行的线程。在这里,每个线程被分为进程

里一个单独的块。每个进程可以含有多个块,可以共享多个块中的数据。程序规定了每个

块中线程的执行时间。所有的请求通过Windows消息队列进行串行化,这样保证了每个

时刻只能访问一个块,因而只有一个单独的进程可以在某一个时刻得到执行。这种模型比

单线程模型的好处在于,可以响应同一时刻的多个用户请求的任务而不只是单个用户请求。

但它的性能还不是很好,因为它使用了串行化的线程模型,任务是一个接一个得到执行的。

·多线程块模型(自由线程块模型)

多线程块模型(MTA)在每个进程里只有一个块而不是多个块。这单个块控制着多个

线程而不是单个线程。这里不需要消息队列,因为所有的线程都是相同的块的一个部分,

并且可以共享。这样的程序比单线程模型和STA的执行速度都要块,因为降低了系统的负

载,因而可以优化来减少系统idle的时间。这些应用程序一般比较复杂,因为程序员必须

提供线程同步以保证线程不会并发的请求相同的资源,因而导致竞争情况的发生。这里有

必要提供一个锁机制。但是这样也许会导致系统死锁的发生。

多线程在.NET里如何工作?

在本质上和结构来说,.NET是一个多线程的环境。有两种主要的多线程方法是.NET

所提倡的:使用ThreadStart来开始你自己的进程,直接的(使用

serWorkItem)或者间接的(比如ead,或者调用

BeginInvoke)使用ThreadPool类。一般来说,你可以"手动"为长时间运行的任务创建

一个新的线程,另外对于短时间运行的任务尤其是经常需要开始的那些,进程池是一个非

常好的选择。进程池可以同时运行多个任务,还可以使用框架类。对于资源紧缺需要进行

同步的情况来说,它可以限制某一时刻只允许一个线程访问资源。这种情况可以视为给线

程实现了锁机制。线程的基类是ing。所有线程通过CLI来进行管理。

·创建线程:

创建一个新的Thread对象的实例。Thread的构造函数接受一个参数:

Thread DummyThread = new Thread( new ThreadStart(dummyFunction) );

·执行线程:

使用Threading命名空间里的start方法来运行线程:

();

·组合线程:

经常会出现需要组合多个线程的情况,就是当某个线程需要其他线程的结束来完成自

己的任务。假设DummyThread必须等待DummyPriorityThread来完成自己的任务,我

们只需要这样做:

() ;

·暂停线程:

使得线程暂停给定的秒

(

·中止线程:

如果需要中止线程可以使用如下的代码:

();

·同步

经常我们会遇到需要在线程间进行同步的情况,下面的代码给出了一些方法:

using System;using ing;namespace

SynchronizationThreadsExample{

class SynchronizationThreadsExample{

private int counter = 0;

static void Main( ) {

SynchronizationThreadsExample

SynchronizationThreadsExample();

STE = new

Function( );

}

public void ThreadFunction ( ) {

Thread DummyThread = new Thread( new ThreadStart(SomeFunction) ;

ground=true;

= "First Thread";

( );

ine("Started thread ", );

Thread DummyPriorityThread = new Thread(

ThreadStart(SomeFunction) );

ground=true;

= "Second Thread";

( );

ine("Started thread ", );

( );

( );

new

}

public void SomeFunction( ) {

try {

while (counter < 10) {

int tempCounter = counter;

tempCounter ++;

(1);

counter = tempCounter;

ine( "Thread . SomeFunction: ",,

counter);

}

}

catch (ThreadInterruptedException Ex) {

ine( "Exception in thread ", );

}

finally {

ine( "Thread Exiting. ",);

}

}

}

}

·使用Interlock

C#提供了一个特殊的类叫做interlocked,就是提供了锁机制的实现,我们可以加入

如下的代码实现锁机制:

nction (ref counter);

·使用锁

这是为了锁定代码关键区域以进行同步,锁定代码如下:

lock (this){ Some statements ;}

·使用Monitor

当有需要进行线程管理的时候我们可以使用:

(this);

其他也有一些方法进行管理,这里就不一一提及了。

线程的缺点

线程自然也有缺点,以下列出了一些:

·如果有大量的线程,会影响性能,因为操作系统需要在他们之间切换;

·更多的线程需要更多的内存空间

·线程会给程序带来更多的bug,因此要小心使用

·线程的中止需要考虑其对程序运行的影响

CPU是以时间片的方式为进程分配CUP处理时间的,当一个进程以同步的方式去完

成几件事情时,此进程必须完成了第一件事情以后再做第二件事,如此按顺序地向CPU请

求完成要做的事情。在此单线程的工作模式下,如果把CUP看作是一共有100个时间片

的话,CPU可能一直都只是花了其中的10个时间片来处理当前进程所要做的事情,只是

用到了CPU的10%的时间片,而其他时间都白白浪费了,当然,实际上CPU的工作模式

还是做完一件事以后再去做另一件事,只是CUP的处理速度非常快,很快就处理完成所请

求的情事。

为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而互不干扰,如当前

进程要完成三件事情1、2、3,那么CPU会分别用10%的时间来同时处理这3件事情,

从而让CPU的使用率达到了30%,大大地提高了CPU的利用率。多线程的好处在处理一

些特殊的场合其优势尤其明显。比如下载文件,你要一边下载一边显示进度一边保存,在

这种情况下,如果没有用多线程的话,没有意外的话一般都会把主线程阻塞,比如进度条

的进度根本没有随着已下载的量而变化,堪至是整个窗体都动不了,用多线程就可以很好

地解决这个问题。

这里有一个生活实例可能更好地去理解多线程:回去看你女朋友做饭,正常的话她都

会把洗好的菜(肉)先放到锅里煮,然后一边洗别的菜或处理别的事情,如:洗碗、收拾

桌台准备开饭,人还是一个人,但她同时做几件事情,这样就可以大大地提高效率。总的

一句话就是:CPU还是要花同样多的时间去完成所有的事情,但多线程可以让CPU掺插

地同时做多件事情,在视觉上让用户觉得计算机在同时帮他处理多件事情,更好地改善用

户体验。

了解了多线程的好处以后,就要了解应该在什么样的情况下使用多线程技术。因为并

不是说所有情况下用多线程都是好事,因为多线程的情况下,CPU还要花时间去维护,CPU

处理各线程的请求时在线程间的切换也要花时间,所以一般情况下是可以不用多线程的,

用了有时反而会得不偿失。大多情况下,要用到多线程的主要是需要处理大量的IO操作时

或处理的情况需要花大量的时间等等,比如:读写文件、视频图像的采集、处理、显示、

保存等。

1.快速的关联切换

由于操作系统级的进程独占自己的虚地址空间,调度进程时,系统必须交换地址空间,

因而进程切换时间长。在同一程序内的多个线程共享同一地址空间,因而能使线程快速切

换。例如,10个进程,每个进程10个线程的系统与100个进程、每个进程1个进程

1个线程的系统相比,前者的运行速度要快于后者。

2.系统额外开销小

对多个进程的管理(创建、调度等)有比较大的系统开销。在需要动态创建新进程的

应用中,比如在响应与每个客户的请求而建立一个新的服务进程的服务器应用程序中,这

种开销比较显著。而对线程的管理虽然也会有系统开销,但比进程的小得多。

3.通信很容易实现

为了实现协作,进程或线程之间需要进行数据交换。对于自动共享同一地址空间的各

线程来说,所有的全局数据都可以访问,因而不需要什么特殊手段就能自动实现数据共享。

而进程之间的通信则要复杂得多。

4.线程个数比进程个数多得多

许多多任务操作系统限制用户进程总数,如不少UNIX版本的典型值为40-10

0,这对许多并发应用来说远远不够。在多线程系统中,虽存在线程总数限额,但个数多

得多(OS/2支持4096个线程)


本文标签: 线程 进程 需要 情况 系统