线程与进程学习(一)

(1)进程:

       在进程模型中,计算机上所有可以运行的软件,通常 也包括操作系统,被组织成若干顺序进程简称进程。一个进程就是一个正在执行的程序的实例,包括程序计数器、寄存器和变量的当前值。从概念上说,每个进程拥有他自己的虚拟CPU,而实际上真正的CPU是在各个进程之间切换的。一个CPU一次只能运行一个进程,即使有两个核(或CPU),每个核一次也只能运行一个CPU。

       由于CPU各进程之间来回快速切换的,所以每个 进程执行其运算的速度是不确定的。而且当一个进程再次运行时,其运算速度通常也不可再现。

        进程和程序的区别,通俗的说,我们现在要按照食谱做一个大盘鸡,食谱就是程序,各种原料就是输入数据,做饭的人就是 CPU,而这个做饭的人按照食谱做饭的这个过程就是进程。一个进程是某种类型的一个活动,他有程序、输入、输出以及状态。还有单个 处理器可以被若干进程 分享 ,它会使用某种调度算法决定何时 停止一个进程 的工作,并转而为另一个进程开始服务。

创建进程的方法:

       ①系统初始化

      启动操作系统的时候,通常会创建 若干个进程。其中有些是前台进程,有些是 后台进程。

       ②执行了 正在运行进程所调用的进程创建系统调用

       ③用户请求创建一个新进程

       ④一个批处理作业的初始化

       这种情形仅在大型机的批处理系统中应用。用户在这种系统中(可能是远程的)提交批处理作业。在操作系统认为有资源可运行 另一个作业时,它 会创建一个新的进程,并运行 其输入队列中的 下一个作业。

进程的终止:

       ①正常退出(自愿的)

       ②出错退出(自愿的)

       ③严重错误(非自愿)

       ④被其他进程杀死(非自愿)

进程的状态:

       ①运行状态(该时刻进程实际占有 CPU)

       ②就绪状态(可运行 ,但因为其他进程正在运行而暂时停止)

       ③阻塞状态(除非某种外部事件发生,否则进程不能运行)

(2)线程

      线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

     线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。



    1.新建状态(New): 
        当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码

     2.就绪状态(Runnable)

        一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

        处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

    3.运行状态(Running)

        当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.

    4. 阻塞状态(Blocked)

        线程运行过程中,可能由于各种原因进入阻塞状态:
        1>线程通过调用sleep方法进入睡眠状态;
        2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
        3>线程试图得到一个锁,而该锁正被其他线程持有;
        4>线程在等待某个触发条件;
        ......           

        所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

    5. 死亡状态(Dead)

        有两个原因会导致线程死亡:
        1) run方法正常退出而自然死亡,
        2) 一个未捕获的异常终止了run方法而使线程猝死。
        为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.

 

(3)进程与线程的关系

     小故事:

      计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。一个车间里,可以有很多工人。他们协同完成一个任务。线程就好比车间里的工人。一个进程可以包括多个线程。车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。操作系统的设计,因此可以归结为三点:

(1)以多进程形式,允许多个任务同时运行;

(2)以多线程形式,允许单个任务分成不同的部分运行;

(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

猜你喜欢

转载自taoyongpan.iteye.com/blog/2371796
今日推荐