理解操作系统中的线程_介绍下你理解的操作系统中线程切换过程 - CSDN
  • 此篇博客是博主在学习操作系统过程的笔记,通过写博客加深对进程和线程理解,贴出来希望和大家共同进步。进程和线程操作系统的重点和难点内容,也是互联网面试高频考点,学好进程和线程的相关问题,有利于后续...

    此篇博客是博主在学习操作系统过程中的笔记,通过写博客加深对进程和线程的理解,贴出来希望和大家共同进步。进程和线程是操作系统的重点和难点内容,也是互联网面试高频考点,学好进程和线程的相关问题,有利于后续的多线程编程。

     

     

    进程的定义:

    进程可以定位为一个数据结构及能在其上进行操作的一个程序,百话点,就是程序的一次执行过程。

    线程的定义:

    线程是进程内的一个执行单元,是进程内的一个相对独立、可调度实体

     

    进程的特点:

    1、动态性:进程是程序的一次动态执行过程,表现在创建而生,调度执行,撤销而亡。

    2、并发性:引入进程目的就是为了使程序能与其他程序并发执行,以便提高资源利用率。

    3、独立性:进程是一个能独立运行的基本单位,是系统进行资源分配和调度的基本单位:

    4、异步性:进程运行时各自独立。

    5、结构性:进程=PCB(程序控制块)+程序段+数据段

     

     

    下面讲讲引入进程和线程概念的原因

    在多道程序的环境下,程序的执行属于并发执行,这时候封闭性将消失,并具有间断性和不可再现性,由于程序执行结果的不可预测性,程序是不能参与并发执行的。为了能够是的程序并发执行,并且能够对程序加以描述和控制,引入了进程的概念。

     

    系统在创建进程和撤销进程需要系统位置分配和回收资源,为了减少程序并发执行过程中所付出的时空开销,是操作系统具有更好的并发性,引入了线程的概念。

     

    从以下四个方面对线程和进程进行比较

    1、调度性:在传统的操作系统中,进程是拥有资源和独立调度的基本单位;而引入线程的操作系统中,进程的调度功能交给线程,线程成为独立调度的基本单位,这时候进程是资源拥有的基本单位。在同一个进程中,线程的切换不会造成进程的切换,而在不同进程中,线程的切换会导致进程的切换。

    2、并发性:引入线程后,进程之间可以并发执行,线程之间也可以并发执行。

    3、拥有资源:进程是拥有资源的基本单位,在引入线程的操作系统中,线程不拥有资源,但是可以访问其所在进程的资源。

    4、系统开销:系统在创建进程和撤销进程需要系统位置分配和回收资源,操作系统所付出的开销远大于穿件和撤销线程时的开销。在进程切换,涉及到整个CPU环境保存以及新调度到进程的CPU的环境设置;在线程切换时,只需要保留和设置少量寄存器内容,开销较小。另外,由于线程共享进程的地址空间,因此线程同步较容易实现,甚至不需要操作系统来干预。

    展开全文
  • 操作系统中进程和线程的概念理解 进程,是指可以在操作系统中独立运行并且作为资源分配的基本单位。多个进程之间可以并发执行(注意这里的并发执行和并行执行并不是一个概念)。 不同进程之间的切换会浪费较高的...

    操作系统中进程和线程的概念理解

    进程,是指可以在操作系统中独立运行并且作为资源分配的基本单位。多个进程之间可以并发执行(注意这里的并发执行和并行执行并不是一个概念)。

    不同进程之间的切换会浪费较高的系统资源,为了提高系统资源利用率和吞吐量。人们又引入了线程的概念。

    线程,是操作系统中作为调度和分派的基本单位,可以理解为轻量级进程。一个进程下可以拥有一个或多个线程,线程在系统中也不能独立于进程之外而存在。

    所谓线程,比进程拥有更少的资源,并且同一进程下的不同线程之间可以共享该进程所拥有的资源。所以当进行线程切换时系统的开销明显小于进程切换。

    线程的并发性比进程要高,这是由线程的基本属性决定的。线程能够更好的支持多处理机系统。

    对于线程的理解可以联系程序中的函数,程序中入口函数main()便是主线程,至于多线程编程就是新建线程函数使得新的函数能和main()函数同时执行(注意这里的同时执行仅仅是我们将任务交付给系统,至于系统底层是并发执行还是并行执行并不是我们能决定的)。


    注:
    1、 并行执行和并发执行的区别:

    a) 并行执行为多个处理机同时对不同的线程任务进行运算处理(现在好多电脑都是多核处理器,所以能进行真正意义上的并行运算)
    b) 并发执行为单个处理机以时间片轮转的方式对多个线程进行处理,宏观上用户体验为同时发生的状态。(因为时间片很短通常以毫秒为单位)
    c) 现在Hadoop框架便是建立在集群的基础上,通过对多个服务器的协调实现并行运算。

    2、 系统底层执行方式与编程无关

    a) 值得说明的是我们编程时还要考虑同步问题,这是因为系统底层的操作相对于我们是封装的,我们将多个线程交付给系统后,得到的只是顺序混乱的结果。就像我们将条理分明的猪肉放入碎肉机得到的是肥瘦混合的五花肉一样。
    b) 对于这样的五花肉并不是我们想要的结果,这样没有保证程序在每次执行后的结果一致性。这样的程序是不可靠的。所以我们在编程时还要考虑多线程的同步问题。
    c) 另一点要区别的是操作系统中的线程同步和编程中的线程同步。编程中的线程同步原因上面已经说明,而操作系统中的线程同步则是因为CPU将内存中的数据拷贝至寄存器时进行不同的运算后重新放入内存时产生冲突。这里可以类比下数据库中的并发控制中的“脏”数据问题。

    展开全文
  • 1.操作系统线程模型1.1 线程实现在用户空间下 当线程在用户空间下实现时,操作系统对线程的存在一无所知,操作系统只能看到进程,而不能看到线程。所有的线程都是在用户空间实现。在操作系统看来,每一个进程只有一...

    1.操作系统线程模型

    1.1 线程实现在用户空间下

    当线程在用户空间下实现时,操作系统对线程的存在一无所知,操作系统只能看到进程,而不能看到线程。所有的线程都是在用户空间实现。在操作系统看来,每一个进程只有一个线程。过去的操作系统大部分是这种实现方式,这种方式的好处之一就是即使操作系统不支持线程,也可以通过库函数来支持线程。

    我们换一种通俗的方式来讲解这段话,首先就是在这在模型下,程序员需要自己实现线程的数据结构、创建销毁和调度维护。也就相当于需要实现一个自己的线程调度内核,而同时这些线程运行在操作系统的一个进程内,最后操作系统直接对进程进行调度。

    这里写图片描述

    这样做有一些优点,首先就是确实在操作系统中实现了真实的多线程,其次就是线程的调度只是在用户态,减少了操作系统从内核态到用户态的切换开销。

    当然缺点也很明显:

    这种模式最致命的缺点也是由于操作系统不知道线程的存在,因此当一个进程中的某一个线程进行系统调用时,比如缺页中断而导致线程阻塞,此时操作系统会阻塞整个进程,即使这个进程中其它线程还在工作。还有一个问题是假如进程中一个线程长时间不释放CPU,因为用户空间并没有时钟中断机制,会导致此进程中的其它线程得不到CPU而持续等待。

    1.2 线程实现在操作系统内核中

    内核线程就是直接由操作系统内核(Kernel)支持的线程,这种线程由内核来完成线程切换,内核通过操纵调度器(Scheduler)对线程进行调度,并负责将线程的任务映射到各个处理器上。每个内核线程可以视为内核的一个分身,这样操作系统就有能力同时处理多件事情,支持多线程的内核就叫做多线程内核(Multi-Threads Kernel)。

    通俗的将就是,程序员直接使用操作系统中已经实现的线程,而线程的创建、销毁、调度和维护,都是靠操作系统(准确的说是内核)来实现,程序员只需要使用系统调用,而不需要自己设计线程的调度算法和线程对CPU资源的抢占使用。

    而不得提到的就是,Linux下的轻量级进程,因为Linux并不像Windows那样,真正的实现了线程的数据结构,而是直接采用了和系统中进程一样的实现方式。

    目前的Linux已经基于NPTL实现了更符合POSIX标准的线程,之前我学习到的LinuxThreads早已经被替代,这里为自己的不求甚解反省。

    轻量级进程(LWP)是建立在内核之上并由内核支持的用户线程,它是内核线程的高度抽象,每一个轻量级进程都与一个特定的内核线程关联。内核线程只能由内核管理并像普通进程一样被调度。

    这里写图片描述

    Linux中程序一般不会直接去使用内核线程,而是去使用内核线程的一种高级接口–轻量级进程,轻量级进程就是我们通常意义上所讲的线程,由于每个轻量级进程都由一个内核线程支持,因此只有先支持内核线程,才能有轻量级进程。 这种轻量级进程与内核线程之间1:1的关系称为一对一的线程模型。

    这里要说明的是,一对一的线程模型是一种概念,Linux是一对一的线程模型,上面的表述太绕了,现在的Linux中线程已经的被更优雅的实现了。

    PS:其实Linux中的pthread库就是调用了轻量级线程接口,来在操作系统中创建一个内核线程。

    Pthread库目前也是基于NPTL实现,已经是一种符合POSIX标准的线程模型了,Linux摆脱了原来LWP的阴影。Linux线程变化

    1.3使用用户线程加轻量级进程混合实现

    在这种混合实现下,即存在用户线程,也存在轻量级进程。用户线程还是完全建立在用户空间中,因此用户线程的创建、切换、析构等操作依然廉价,并且可以支持大规模的用户线程并发。而操作系统提供支持的轻量级进程则作为用户线程和内核线程之间的桥梁,这样可以使用内核提供的线程调度功能及处理器映射,并且用户线程的系统调用要通过轻量级进程来完成,大大降低了整个进程被完全阻塞的风险。在这种混合模式中,用户线程与轻量级进程的数量比是不定的,即为N:M的关系:

    这里写图片描述

    明白了前面两种模型,就应该很好理解这种线程模型了,但实际上现在主流的操作系统已经不太常用这种线程模型了。

    2019.3.26更新:目前来说,作为异步回调以外的另一种解决方案,这种m:n的线程模型可以说大有可为,Golang的协程就是使用了这种模型,在用户态,协程能快速的切换,避免了线程调度的CPU开销问题,协程相当于线程的线程。

    2.Java线程

    2.1 Java线程在操作系统上本质:

    Java线程在JDK1.2之前,是基于称为“绿色线程”(Green Threads)的用户线程实现的,而在JDK1.2中,线程模型替换为基于操作系统原生线程模型来实现。因此,在目前的JDK版本中,操作系统支持怎样的线程模型,在很大程度上决定了Java虚拟机的线程是怎样映射的,这点在不同的平台上没有办法达成一致,虚拟机规范中也并未限定Java线程需要使用哪种线程模型来实现。线程模型只对线程的并发规模和操作成本产生影响,对Java程序的编码和运行过程来说,这些差异都是透明的。

    也就说JDK1.2之前,**程序员们为JVM开发了自己的一个线程调度内核,而到操作系统层面就是用户空间内的线程实现。**而到了JDK1.2及以后,JVM选择了更加稳健且方便使用的操作系统原生的线程模型,通过系统调用,将程序的线程交给了操作系统内核进行调度

    对于Sun JDK来说,它的Windows版与Linux版都是使用一对一的线程模型实现的,一条Java线程就映射到一条轻量级进程之中,因为Windows和Linux系统提供的线程模型就是一对一的。

    也就是说,现在的Java中线程的本质,其实就是操作系统中的线程,Linux下是基于pthread库实现的轻量级进程,Windows下是原生的系统Win32 API提供系统调用从而实现多线程

    2.2 Java中的线程

    这里写图片描述

    特别注意:这些线程的状态时JVM中的线程状态!不是操作系统中的线程状态。

    2.2.1 操作系统中的进程(线程)状态**(区分和JVM中的线程状态)**

    这里写图片描述

    这里需要着重解释一点,在现在的操作系统中,因为线程依旧被视为轻量级进程,所以操作系统中线程的状态实际上和进程状态是一致的模型。

    2.2.2 操作系统中线程和Java线程状态的关系:

    从实际意义上来讲,操作系统中的线程除去newterminated状态,一个线程真实存在的状态,只有:

    • ready表示线程已经被创建,正在等待系统调度分配CPU使用权。
    • running表示线程获得了CPU使用权,正在进行运算
    • waiting表示线程等待(或者说挂起),让出CPU资源给其他线程使用

    为什么除去newterminated状态?是因为这两种状态实际上并不存在于线程运行中,所以也没什么实际讨论的意义。

    对于Java中的线程状态:

    无论是Timed WaitingWaiting还是Blocked,对应的都是操作系统线程的**waiting(等待**)状态。
    Runnable状态,则对应了操作系统中的readyrunning状态。

    而对不同的操作系统,由于本身设计思路不一样,对于线程的设计也存在种种差异,所以JVM在设计上,就已经声明:

    虚拟机中的线程状态,不反应任何操作系统线程状态
    

    所以我上面说的那么多,只是作为理解模型,Java线程和操作系统线程,实际上同根同源,但又相差甚远。


    参考资料:

    展开全文
  • 本人不才,应读者要求新开专栏,与各位读者分享自己对JAVA线程技术的理解和使用经验。这个专栏将分成两个部分:线程基础知识和锁知识。专栏的难度应该是我所开专栏难度最低的一个,着重于线程基础知识的讲解,更...

    1、概述

    我在写“系统间通信技术专栏”的时候,收到很多读者的反馈。其中有一部分读者希望我抽空写一写自己关于对JAVA线程的使用经验和总结。巧的是,这个月我所在的技术团队也有很多同事跟我讨论关于JAVA中线程的操作。正好本月我工作也不是很忙,除了继续推进我的重点专栏“系统间通信技术”外,可以更多的空余时间跟各位读者分享自己对JAVA线程技术的理解和使用经验。

    本人不才,应读者要求新开专栏,与各位读者分享自己对JAVA线程技术的理解和使用经验。这个专栏将分成两个部分:线程基础知识和锁知识。专栏的难度应该是我所开专栏中难度最低的一个,着重于线程基础知识的讲解,更适合JAVA初学者阅读,目的是希望能够帮助大家提高codeing水平和程序质量。如果您是经验老道的高手也欢迎和本人讨论相关问题,对本人文章的论点进行勘误,您的支持是我写作的关键动力。当然本人的更多精力还是放在继续完成“系统间通信技术”这个专栏。(本系列的博客文章将不会置顶)

    2、操作系统和线程原理

    线程是一个操作系统级别的概念。JAVA语言(包括其他编程语言)本身不创建线程;而是调用操作系统层提供的接口创建、控制、销毁线程实例。

    这里写图片描述

    • 首先要说明的是,根据操作系统的不同(Windows/Unix/Linux/其他),他们所支持的线程底层实现和操作效果也是不尽相同的。不过一个操作系统支持的线程至少会有四种状态:就绪、执行、阻塞和终结。线程在四种状态下进行切换,都是要消耗不少的CPU计算能力的

    • 并且根据操作系统使用线程的进程的不一样,线程还分为用户线程和操作系统线程。操作系统线程(内核线程),是指操作系统内核为了完成硬件接口层操作,由操作系统内核创建的线程:例如I/O操作的内核线程,这些线程应用程序是不能干预的;用户线程,是指用户安装/管理的应用程序,为执行某一种操作,而由这个应用程序创建的线程。后文我们讨论的JAVA线程,都是用户级线程

    • 线程在创建时,操作系统不会为这个线程分配独立的资源(除了必要的数据支撑)。一个应用程序(进程)下的所有线程,都是共享这个应用程序(进程)中的资源,例如这个应用程序的CPU资源、I/O资源、内存资源。

    • 现在基本上主流操作系统都支持多线程实现。即一个应用程序中(一个进程中),可以创建多个线程。一个应用程序下,各个线程间都可以进行通讯、可以进行状态互操作。且一个进程中,至少有一个线程存在。

    3、JAVA中最简单的线程示例

    JAVA中提供了丰富的操作系统接口实现,帮助我们进行线程操作。这些实现分布在java的java.lang基础包、java.io基础包和java.util.concurrent工具包当中;这个专栏所涉及到的代码示例也会从易到难向大家进行演示。我们先来看看JAVA中最基本的线程操作实现(高手请绕行)。

    3-1、Thread父类

    java.lang.Thread类是JAVA中用于实现线程操作的最基本的类之一。您可以创建一个集成Thread类的子类来定义您自己的线程实现:

    package test.thread.base;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.log4j.BasicConfigurator;
    
    public class MyDefindThread extends Thread {
    
        static {
            BasicConfigurator.configure();
        }
    
        /**
         * 日志。一定要使用Log4j才行。否则你就用System.out吧
         */
        private static final Log LOGGER= LogFactory.getLog(MyDefindThread.class);
    
        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            Long threadId =  this.getId();
            MyDefindThread.LOGGER.info("线程(" + threadId + ")做了一些事情,然后结束了。");
        }
    
        public static void main(String[] args) throws Exception {
            new MyDefindThread().start();
        }
    }

    3-2、Runable接口

    除了可以继承java.lang.Thread类来定义自己的线程外,您还可以实现java.lang.Runnable接口来定义一个线程(一般情况,我们优先使用这种方式):

    package test.thread.base;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.log4j.BasicConfigurator;
    
    public class MyDefindRunnable implements Runnable {
    
        static {
            BasicConfigurator.configure();
        }
    
        /**
         * 日志。一定要使用Log4j才行。否则你就用System.out吧
         */
        private static final Log LOGGER= LogFactory.getLog(MyDefindThread.class);
    
        /* (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            // 获取当前线程的ID
            long threadId = Thread.currentThread().getId();
            MyDefindRunnable.LOGGER.info("线程(" + threadId + ")做了一些事情,然后结束了。");
        }
    
        public static void main(String[] args) throws Exception {
            new Thread(new MyDefindRunnable()).start();
        }
    }

    以上的两段代码都没有太多可讲解的。您可以在调试环境下观察到JAVA应用程序是如何运行线程的:

    这里写图片描述

    4、下文介绍

    下一篇文章中,我们将继续介绍Java所支持的线程间基本互操作,包括:阻塞、唤醒、终止等操作;然后介绍Java原生线程池的工作原理和基本操作。

    展开全文
  • 这篇文章要讨论的是Java编程的多线程操作系统中的多线程的区别问题。 线程状态。首先两者的线程状态是一样的。(创建、就绪、执行、阻塞、终止),其实这五个状态也是进程的状态。 那么Java的多线程 和 OS...
  • 这篇博文简单介绍一下操作系统中线程运行状态,为后文继续介绍操作系统的调度器做一些准备的工作。 为了分时的复用硬件的处理器资源,操作系统需要通过上下文切换将不同的调度实例(一般是线程)分时的在处理器上...
  • 先说多线程模型,参考...中文版是《操作系统概念,第9版》 https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/4_Threads.html 一个线程是CPU利用率的基本单元,包括一个程序计数器,堆栈,一组寄存...
  • 理解这个概念,须要先了解一下操作系统的一些相关概念。大部分操作系统(如Windows、Linux)的任务调度是采用时间片轮转的抢占式调度方式,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流...
  • 文章目录为什么要说线程的切换线程...操作系统是多进程的,我们关注的应该是进程之间的切换,那为什么关注线程的切换呢?因为理解线程的切换之后可以更好的理解进程的切换,换句话说线程的切换是进程切换的基础。...
  •  在传统的操作系统中,进程拥有独立的内存地址空间和一个用于控制的线程。但是,现在的情况更多的情况下要求在同一地址空间下拥有多个线程并发执行。因此线程被引入操作系统。   为什么需要线程?  ...
  • 首先需要回答一个问题,为什么操作系统需要线程。如果非要说是为什么需要线程,还不如说为什么需要进程还有其它进程。这些进程包含的其它迷你进程就是线程。进程有以下缺陷: 1、进程只能在一个时间内干一件事...
  • 一、用户级线程 如何只切换指令,而资源不动? ——线程切换+映射表切换=进程切换(在内存管理之后讲),先搞懂线程切换,再做进程切换 线程切换即只切换指令序列(即只有PC变化和寄存器变化),而其他资源不进行...
  • 系统的硬件组成为了理解一个程序运行时发生了什么,需要理解一个典型系统的硬件组织. - 总线总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束。按照计算机所传输的信息种类...
  • 关于进程和线程,大家总是说的一句话是“进程是操作系统分配资源的最小单元,线程操作系统调度的最小单元”。这句话理论上没问题,我们来看看什么是所谓的“资源”呢。   什么是计算机资源 经典的冯诺依曼结构...
  • 《编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程》一文详细讲述了线程、进程的关系及在操作系统中的表现,《编程思想之多线程与多进程(2)——线程优先级与线程安全》一文讲了线程安全(各种同步锁)...
  • 关于操作系统线程、进程和任务的区别域联系,网上相关的文章或者博文多不胜数,二级户每一本关于操作系统原理的书籍都会有相关的内容。本文仅作为自己学习操作系统原理的学习日志。如果有幸被网友阅读,请积极指正...
  • 深刻理解线程和进程的概念,掌握线程与进程在组成成分上的差别,以及与其相适应的通讯方式和应用目标 (二) 实验内容 以Linux系统进程和线程机制为背景,掌握fork()和clone()系统调用的形式和功能,以及与其相适应...
  • 操作系统之进程调度——优先权法和轮转法(附上样例讲解) 操作系统之银行家算法—详解流程及案例数据 操作系统之多线程编程—读者优先/写者优先详解 操作系统之存储管理——FIFO算法和LRU算法 操作系统之磁盘...
  • Java 多线程理解

    2018-08-18 00:19:41
    Java的程序是多线程的, 一个简单的程序包含了两个线程, 即main程序主入口,还有个是gc ,垃圾回收机制的线程线程跟进程的区别: 进程是程序执行的一个过程,它是一个动态的概念, 进程最少有5种基本...
  • 之前降解过内核线程、轻量级进程、用户线程三种线程概念解惑(线程≠轻量级进程), 但是一直对其中提到的线程的实现模型比较迷惑, 这次就花了点时间怎么学习了一下子1 线程的3种实现方式在传统的操作系统中,拥有...
1 2 3 4 5 ... 20
收藏数 360,591
精华内容 144,236
关键字:

理解操作系统中的线程