进程与线程

来源:互联网 发布:火车头采集数据库发布 编辑:程序博客网 时间:2024/06/03 22:02

  操作系统中进程是资源分配的单位,线程是调度的单位。

  1.1进程

   在多道程序环境下,程序的执行属于并发执行,此时它们将失去其封闭性,并具有间断性及不可再现性的特征。这决定了通常的程序是不能参与并发执行的,因为程序执行的结果是不可再现的。这样,程序的运行也就失去了意义。为使程序能并发执行,且为了对并发执行的程序加以描述和控制,人们引入了“进程”的概念。

  进程的状态:

  进程执行时的间断性决定了进程可能具有多种状态。事实上,运行中的进程可能具有以下三种基本状态。

   1) 就绪(Ready)状态

  当进程已分配到除 CPU 以外的所有必要资源后,只要再获得 CPU,便可立即执行,进程这时的状态称为就绪状态。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。

   2) 执行状态

  进程已获得 CPU,其程序正在执行。在单处理机系统中,只有一个进程处于执行状态;在多处理机系统中,则有多个进程处于执行状态。

   3) 阻塞状态

  正在执行的进程由于发生某事件而暂时无法继续执行时,便放弃处理机而处于暂停状态,亦即进程的执行受到阻塞,把这种暂停状态称为阻塞状态,有时也称为等待状态或封锁状态。致使进程阻塞的典型事件有:请求 I/O,申请缓冲空间等。通常将这种处于阻塞状态的进程也排成一个队列。有的系统则根据阻塞原因的不同而把处于阻塞状态的进程排成多个队列。

处于就绪状态的进程,在调度程序为之分配了处理机之后,该进程便可执行,相应地,它就由就绪状态转变为执行状态。正在执行的进程也称为当前进程,如果因分配给它的时间片已完而被暂停执行时,该进程便由执行状态又回复到就绪状态;如果因发生某事件而使进程的执行受阻(例如,进程请求访问某临界资源,而该资源正被其它进程访问时),使之无法继续执行,该进程将由执行状态转变为阻塞状态。

 1.2线程

  线程具有许多传统进程所具有的特征,所以又称为轻型进程(Light-Weight Process)或进程元,相应地把传统进程称为重型进程(Heavy-WeightProcess),传统进程相当于只有一个线程的任务。在引入了线程的操作系统中,通常一个进程都拥有若干个线程,至少也有一个线程

  线程的状态和进程大体差不多,不想赘述。

 1.3内核线程

   前两点都是抄的计算机操作系统书上的内容,内核线程还是挺有意思的,在我学习操作系统的时候,知道了一个进程内会有多个线程,但是同一个进程内多个线程不能同时在处理器上运行,这我就很疑惑了,那怎么利用多核处理器的优势,那有的人会说,多处理器可以同时分配给多个不同的进程,让不同的进程中的线程同时运行啊,那我们平时写程序时,比如写Java多线程时,同一进程下的多个线程怎么实现并行(同一进程下,多个线程可以实现并发,注意是并发),直到了解了内核线程解答了我的顾虑。

   对于通常的进程,无论是系统进程还是用户进程,进程的创建、 撤消,以及要求由系统设备完成的 I/O 操作,都是利用系统调用而进入内核,再由内核中的相应处理程序予以完成的。进程的切换同样是在内核的支持下实现的。因此我们说,不论什么进程,它们都是在操作系统内核的支持下运行的,是与内核紧密相关的。

这里所谓的内核支持线程 KST(Kernel Supported Threads),也都同样是在内核的支持下运行的,即无论是用户进程中的线程,还是系统进程中的线程,他们的创建、撤消和切换等也是依靠内核,在内核空间实现的。此外,在内核空间还为每一个内核支持线程设置了一个线程控制块,内核是根据该控制块而感知某线程的存在,并对其加以控制。

  这种线程实现方式主要有如下四个优点:
  1) 在多处理器系统中,内核能够同时调度同一进程中多个线程并行执行;
  2) 如果进程中的一个线程被阻塞了,内核可以调度该进程中的其它线程占有处理器运

行,也可以运行其它进程中的线程;
  3) 内核支持线程具有很小的数据结构和堆栈,线程的切换比较快,切换开销小;
  4) 内核本身也可以采用多线程技术,可以提高系统的执行速度和效率。内核支持线程的主要缺点是:对于用户的线程切换而言,其模式切换的开销较大,在  

  同一个进程中,从一个线程切换到另一个线程时,需要从用户态转到内核态进行,这是因为用户进程的线程在用户态运行,而线程调度和管理是在内核实现的,系统开销较大。 

  正是内核线程的特点,同一进程下的多线程能够并行,Java的线程是1对1映射到内核线程的,所以Java在多线程的支持上有天生的优势,用Java来写多线程的程序会很方便。

1.4Java线程的创建机制

  我们在主线程中创建子线程,那么创建的线程初始化是由子线程来进行还是由主线程来进行初始化?

  通过一个程序来看看:

package Thread;/** * Created by Jackie on 2017/9/2. */public class ThreadCreat {    public static void main(String[] args){        System.out.println("main thread is running");        Thread.currentThread().setName("main thread");        System.out.println(Thread.currentThread().getName());        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        new Son("son").start();    }}class Son extends Thread{    public Son(String name){        setName(name);        System.out.println(Thread.currentThread().getName());    }    @Override    public void run() {        System.out.println("son is running");        System.out.println(Thread.currentThread().getName());    }}

  运行结果是:

main thread is running
main thread
main thread
son is running
son


Process finished with exit code 0

  从运行结果来看,子线程的初始化是由主线程来进行的,初始化后映射为内核线程,之后是由操作系统来调度运行。

 


原创粉丝点击