函数概念的发展历史 线程 线程-线程概念,线程-发展历史

线程,计算机科学术语,有时也被称为轻量级进程(Light?Weight?Process,LWP),它是运行中的程序的调度单位。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。线程被包含在进程之中,是进程的一个实体,是CPU调度和分派的基本单位它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

线程_线程 -线程概念


线程一般来说,我们把正在计算机中执行的程序叫做"进程"(Process),而不将其称为程序(Program)。所谓"线程"(Thread),是"进程"中某个单一顺序的控制流。
新兴的操作系统,如Mac,WindowsNT,Windows95等,大多采用多线程的概念,把线程视为基本执行单位。线程也是Java中的相当重要的组成部分之一。
甚至最简单的Applet也是由多个线程来完成的。在Java中,任何一个Applet的paint()和update()方法都是由AWT(AbstractWindowToolkit)绘图与事件处理线程调用的,而Applet主要的里程碑方法――init(),start(),stop()和destory()――是由执行该Applet的应用调用的。
单线程的概念没有什么新的地方,真正有趣的是在一个程序中同时使用多个线程来完成不同的任务。某些地方用轻量进程(LightweightProcess)来代替线程,线程与真正进程的相似性在于它们都是单一顺序控制流。然而线程被认为轻量是由于它运行于整个程序的上下文内,能使用整个程序共有的资源和程序环境。
作为单一顺序控制流,在运行的程序内线程必须拥有一些资源作为必要的开销。例如,必须有执行堆栈和程序计数器。在线程内执行的代码只在它的上下文中起作用,因此某些地方用"执行上下文"来代替"线程"。

线程_线程 -发展历史

线程的引入
60年代,在OS中能拥有资源和独立运行的基本单位是进程,然而随着计算机技术的发展,进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。
因此在80年代,出现了能独立运行的基本单位――线程(Threads)。

线程_线程 -工作原理


线程

线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程不拥有系统资源,只有运行必须的一些数据结构;它与父进程的其它线程共享该进程所拥有的全部资源。进程可以创建和撤消线程,从而实现程序的并发执行。一般,线程具有就绪、阻塞和运行三种基本状态。

在多中央处理器的系统里,不同线程可以同时在不同的中央处理器上运行,甚至当它们属于同一个进程时也是如此。大多数支持多处理器的操作系统都提供编程接口来让进程可以控制自己的线程与各处理器之间的关联度(affinity)。

有时候,线程也称作轻量级进程。就象进程一样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。它们共享内存、文件句柄和其它每个进程应有的状态。

进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而且它们从同一堆中分配对象。尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。

Java 线程工具和API看似简单。但是,编写有效使用线程的复杂程序并不十分容易。因为有多个线程共存在相同的内存空间中并共享相同的变量,所以您必须小心,确保您的线程不会互相干扰。

线程_线程 -相关概念

为了正确有效地使用线程,必须理解线程的各个方面并了解Java 实时系统。必须知道如何提供线程体、线程的生命周期、实时系统,如何调度线程、线程组、什么是幽灵线程(Demo nThread)。

(1)线程体

所有的操作都发生在线程体中,在Java中线程体是从Thread类继承的run()方法,或实现Runnable接口的类中的run()方法。当线程产生并初始化后,实时系统调用它的run()方法。run()方法内的代码实现所产生线程的行为,它是线程的主要部分。

(2)线程状态

附图表示了线程在它的生命周期内的任何时刻所能处的状态以及引起状态改变的方法。这图并不是完整的有限状态图,但基本概括了线程中比较感兴趣和普遍的方面。以下讨论有关线程生命周期以此为据。

新线程态(New Thread)
产生一个Thread对象就生成一个新线程。当线程处于"新线程"状态时,仅仅是一个空线程对象,它还没有分配到系统资源。因此只能启动或终止它。任何其他操作都会引发异常。

可运行态(Runnable)
start()方法产生运行线程所必须的资源,调度线程执行,并且调用线程的run()方法。在这时线程处于可运行态。该状态不称为运行态是因为这时的线程并不总是一直占用处理机。特别是对于只有一个处理机的PC而言,任何时刻只能有一个处于可运行态的线程占用处理 机。Java通过调度来实现多线程对处理机的共享。

非运行态(Not Runnable)
当以下事件发生时,线程进入非运行态。
①suspend()方法被调用;
②sleep()方法被调用;
③线程使用wait()来等待条件变量;
④线程处于I/O等待。

死亡态(Dead)
当run()方法返回,或别的线程调用stop()方法,线程进入死亡态 。通常Applet使用它的stop()方法来终止它产生的所有线程。

(3)线程优先级

虽然我们说线程是并发运行的。然而事实常常并非如此。正如前面谈到的,当系统中只有一个CPU时,以某种顺序在单CPU情况下执行多线程被称为调度(scheduling)。Java采用的是一种简单、固定的调度法,即固定优先级调度。这种算法是根据处于可运行态线程的相对优先级来实行调度。当线程产生时,它继承原线程的优先级。在需要时可对优先级进行修改。在任何时刻,如果有多条线程等待运行,系统选择优先级最高的可运行线程运行。只有当它停止、自动放弃、或由于某种原因成为非运行态低优先级的线程才能运行。如果两个线程具有相同的优先级,它们将被交替地运行。

Java实时系统的线程调度算法还是强制性的,在任何时刻,如果一个比其他线程优先级都高的线程的状态变为可运行态,实时系统将选择该线程来运行。

(4)幽灵线程

任何一个Java线程都能成为幽灵线程。它是作为运行于同一个进程内的对象和线程的服务提供者。例如,HotJava浏览器有一个称为" 后台图片阅读器"的幽灵线程,它为需要图片的对象和线程从文件系统或网络读入图片。

幽灵线程是应用中典型的独立线程。它为同一应用中的其他对象和线程提供服务。幽灵线程的run()方法一般都是无限循环,等待服务请求。

(5)线程组

每个Java线程都是某个线程组的成员。线程组提供一种机制,使得多个线程集于一个对象内,能对它们实行整体操作。譬如,你能用一个方法调用来启动或挂起组内的所有线程。Java线程组由ThreadGroup类实现。
当线程产生时,可以指定线程组或由实时系统将其放入某个缺省的线程组内。线程只能属于一个线程组,并且当线程产生后不能改变它所属的线程组。

线程_线程 -线程好处

使用线程可以把占据长时间的程序中的任务放到后台去处理,用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度・程序的运行速度可能加快・在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较游泳了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

线程_线程 -与进程的比较

进程是资源分配的基本单位。所有与该进程有关的资源,都被记录在进程控制块PCB中。以表示该进程拥有这些资源或正在使用它们。
另外,进程也是抢占处理机的调度单位,它拥有一个完整的虚拟地址空间。

与进程相对应,线程与资源分配无关,它属于某一个进程,并与进程内的其他线程一起共享进程的资源。
当进程发生调度时,不同的进程拥有不同的虚拟地址空间,而同一进程内的不同线程共享同一地址空间。

线程只由相关堆栈(系统栈或用户栈)寄存器和线程控制表TCB组成。寄存器可被用来存储线程内的局部变量,但不能存储其他线程的相关变量。

发生进程切换与发生线程切换时相比较,进程切换时涉及到有关资源指针的保存以及地址空间的变化等问题;线程切换时,由于同不进程内的线程共享资源和地址 空间,将不涉及资源信息的保存和地址变化问题,从而减少了操作系统的开销时间。而且,进程的调度与切换都是由操作系统内核完成,而线程则既可由操作系统内 核完成,也可由用户程序进行。

线程_线程 -适用范围


线程

典型的应用

1.服务器中的文件管理或通信控制

2.前后台处理

3.异步处理

线程_线程 -基本操作

派生:线程在进程内派生出来,它即可由进程派生,也可由线程派生。


线程的状态与操作
阻塞(Block):如果一个线程在执行过程中需要等待某个事件发生,则被阻塞。
激活(unblock):如果阻塞线程的事件发生,则该线程被激活并进入就绪队列。
调度(schedule):选择一个就绪线程进入执行状态。
结束(Finish):如果一个线程执行结束,它的寄存器上下文以及堆栈内容等将被释放。

线程的另一个执行特性是同步。线程中所使用的同步控制机制与进程中所使用的同步控制机制相同。

线程_线程 -状态变化

(1)创建线程
当创建一个新的进程时,也创建一个新的线程,进程中的线程可以在同一进程中创建新的线程中创建新的线程。

(2)终止线程
可以正常终止自己,也可能某个线程执行错误,由其它线程强行终止。终止线程操作主要负责释放线程占有的寄存器和栈。

(3)阻塞线程

当线程等待每个事件无法运行时,停止其运行。

(4)唤醒线程
当阻塞线程的事件发生时,将被阻塞的线程状态置为就绪态,将其挂到就绪队列。进程仍然具有与执行相关的状态。例如,所谓进程处于“执行”状态,实际上是指该进程中的某线程正在执行。对进程施加的与进程状态有关的操作,也对其线程起作用。例如,把某个进程挂起时,该进程中的所有线程也都被挂起,激活也是同样。

线程_线程 -线程分类

线程有两个基本类型

用户级线程

管理过程全部由用户程序完成,操作系统内核心只对进程进行管理。

系统级线程

系统级线程也是核心级线程,由操作系统内核进行管理。操作系统内核给应用程序提供相应的系统调用和应用程序接口API,以使用户程序可以创建、执行、撤消线程。

线程_线程 -线程举例

1.UnixInternational线程

SUN Solaris操作系统使用的线程叫做UnixInternational线程,支持内核线程、轻权进程和用户线程。一个进程可有大量用户线程;大量用户线程复用少量的轻权进程,轻权进程与内核线程一一对应。
用户级线程在调用核心服务时(如文件读写),需要“捆绑(bound)”在一个lwp上。永久捆绑(一个LWP固定被一个用户级线程占用,该LWP移到LWP池之外)和临时捆绑(从LWP池中临时分配一个未被占用的LWP)。
在调用系统服务时,如果所有LWP已被其他用户级线程所占用(捆绑),则该线程阻塞直到有可用的LWP。
如果LWP执行系统线程时阻塞(如read()调用),则当前捆绑在LWP上的用户级线程也阻塞。


用户线程、轻权进程和核心线程的关系
UnixInternational线程的有关API

UNIX International 线程的头文件是<thread.h>。

1.创建用户级线程

intthr_create(void*stack_base,size_tstack_size,void*(*start_routine)(void*),void*arg,longflags,thread_t*new_thr);

其中flags包括:THR_BOUND(永久捆绑),THR_NEW_LWP(创建新LWP放入LWP池),若两者同时指定则创建两个新LWP,一个永久捆绑而另一个放入LWP池。

2.等待用户级线程

intthr_join(thread_twait_for,thread_t*dead,void**status);

3.挂起用户级线程

intthr_suspend(thread_tthr);

4.继续用户级线程

intthr_continue(thread_tthr);

5.退出用户级线程

voidthr_exit(void*status);

6.返回当前用户级线程的线程标识符

thread_tthr_self(void);


2.POSIX线程

Pthreads(POSIX Thread)的相关API

Pthreads 线程的头文件是<pthread.h>。

1.创建用户级线程

intpthread_create(pthread_t*thread,constpthread_attr_t*attr,void*(*start_routine)(void*),void*arg);

2.等待用户级线程

intpthread_join(pthread_tthread,void**retval);

3.退出用户级线程

voidpthread_exit(void*retval);

4.返回当前用户级线程的线程标识符

pthread_tpthread_self(void);

5.用户级线程的取消

intpthread_cancel(pthread_tthread);

3.C++11线程

C++11线程的头文件是<thread>。

1.创建用户级线程

std::thread::thread(Function&&f,Args&&...args);

2.等待用户级线程结束

std::thread::join();

3.脱离用户级线程控制

std::thread::detach();

4.交换用户级线程

std::thread::swap(thread&other);

4. C11线程

C11线程的头文件是<threads.h>。

C11线程仅仅是个“建议标准”,也就是说100%遵守C11标准的C编译器是可以不支持C11线程的。根据C11标准的规定,只要编译器预定义了__STDC_NO_THREADS__宏,就可以没有<threads.h>头文件,自然也就也没有下列函数。

1.创建用户级线程

intthrd_create(thrd_t*thr,thrd_start_tfunc,void*arg);

2.结束本线程

_Noreturnvoidthrd_exit(intres);

3.等待用户级线程运行完毕

intthrd_join(thrd_tthr,int*res);

函数概念的发展历史 线程 线程-线程概念,线程-发展历史
4.返回当前线程的线程标识符

thrd_tthrd_current();

5. Win32线程

Win32线程的上下文包括:寄存器、核心栈、线程环境块和用户栈。

Win32线程状态(1) 就绪状态:进程已获得除处理机外的所需资源,等待执行。

WindowsNT的线程状态
(2) 备用状态:特定处理器的执行对象,系统中每个处理器上只能有一个处于备用状态的线程。
(3) 运行状态:完成描述表切换,线程进入运行状态,直到内核抢先、时间片用完、线程终止或进行等待状态。
(4) 等待状态:线程等待对象句柄,以同步它的执行。等待结束时,根据优先级进入运行、就绪状态。
(5) 转换状态:线程在准备执行而其内核堆栈处于外存时,线程进入转换状态;当其内核堆栈调回内存,线程进入就绪状态。
(6) 终止状态:线程执行完就进入终止状态;如执行体有一指向线程对象的指针,可将线程对象重新初始化,并再次使用。

Win32线程的有关API
Win32线程的头文件是<Windows.h>,仅适用于Windows操作系统。

1.创建用户级线程

HANDLEWINAPICreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes,SIZE_TdwStackSize,LPTHREAD_START_ROUTINElpStartAddress,LPVOIDlpParameter,DWORDdwCreationFlags,LPDWORDlpThreadId);

2.结束本线程

VOIDWINAPIExitThread(DWORDdwExitCode);

3.挂起指定的线程

DWORDWINAPISuspendThread(HANDLEhThread);

4.恢复指定线程运行

DWORDWINAPIResumeThread(HANDLEhThread);

5.等待线程运行完毕

DWORDWINAPIWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);

6.返回当前线程的线程标识符

DWORDWINAPIGetCurrentThreadId(void);

7.返回当前线程的线程句柄

HANDLEWINAPIGetCurrentThread(void);

6. Java线程


java线程示意1)最简单的情况是,Thread/Runnable的run()方法运行完毕,自行终止。
2)对于更复杂的情况,比如有循环,则可以增加终止标记变量和任务终止的检查点。
3)最常见的情况,也是为了解决阻塞不能执行检查点的问题,用中断来结束线程,但中断只是请求,并不能完全保证线程被终止,需要执行线程协同处理。[6]
4)IO阻塞和等锁情况下需要通过特殊方式进行处理。
5)使用Future类的cancel()方法调用。
6)调用线程池执行器的shutdown()和shutdownNow()方法。
7)守护线程会在非守护线程都结束时自动终止。
8)Thread的stop()方法,但已不推荐使用。

线程_线程 -守护线程

守护线程是特殊的线程,一般用于在后台为其他线程提供服务.
Java中,isDaemon():判断一个线程是否为守护线程.
Java中,setDaemon():设置一个线程为守护线程.
C#守护线程
/**
*本线程设置了一个超时时间
*该线程开始运行后,经过指定超时时间,
*该线程会抛出一个未检查异常通知调用该线程的程序超时
*在超时结束前可以调用该类的cancel方法取消计时
*@authorsolonote
*/

publicclassTimeoutThreadextendsThread{
/**
*计时器超时时间
*/
privatelongtimeout;
/**
*计时是否被取消
*/
privatebooleanisCanceled=false;
/**
*当计时器超时时抛出的异常
*/
privateTimeoutExceptiontimeoutException;
/**
*构造器
*@paramtimeout指定超时的时间
*/
publicTimeoutThread(longtimeout,TimeoutExceptiontimeoutErr){
super();
this.timeout=timeout;
this.timeoutException=timeoutErr;
//设置本线程为守护线程
this.setDaemon(true);
}
/**
*取消计时
*/
publicsynchronizedvoidcancel()
{
isCanceled=true;
}
/**
*启动超时计时器
*/
publicvoidrun()
{
try{
Thread.sleep(timeout);
if(!isCanceled)
throwtimeoutException;
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}

  

爱华网本文地址 » http://www.aihuau.com/a/8103420103/93190.html

更多阅读

第二章 教育技术的发展历史--陈群林考研网 考研网

第二章 教育技术的发展历史出处:http://www.blogchinese.com/06091/256934/archives/2006/2006115173552.shtml【本章学习要点】历史是透视现实与预测未来的一面镜子。了解教育技术的发展历史,可以使教育技术在继承和借鉴的基础上,更好

货币及货币理论的发展历史 货币的发展历史

昨读蔡定创先生的《货币迷局》,其中第一部分是关于货币来历及货币理论的发展历史,感觉非常精彩,讲述极其清晰通俗易懂,而且逻辑性很强,通过对货币及其理论发展的逻辑过程进行考察,从中找出了货币的本质属性,颠覆了传统的货币观念,给出了货币

电晕处理机的发展历史 东莞电晕处理机

【本文摘自《电晕处理综述》(CoronaTreatment:AnOverview),DavidA.Markgraf,SeniorVicePresident,EnerconIndustriesCorporation】HistoryofDevelopment电晕处理技术的发展历史Theconfigurationoftheelectrodehastakenmanyforms.O

声明:《函数概念的发展历史 线程 线程-线程概念,线程-发展历史》为网友懂不懂焚琴煮鹤分享!如侵犯到您的合法权益请联系我们删除