● 请你说一下多进程、多线程,操做系统层面的差异和联系
参考回答:
进程:进程是一个具备必定独立功能的程序在一个数据集上的一次动态执行的过程,是操做系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,历来没有统一的标准定义。进程通常由程序、数据集合和进程控制块三部分组成。程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所须要的数据和工做区;程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的惟一标志。java
线程:在早期的操做系统中并无线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每一个进程有各自独立的一块内存,使得各个进程之间内存地址相互隔离。后来,随着计算机的发展,对CPU的要求愈来愈高,进程之间的切换开销较大,已经没法知足愈来愈复杂的程序的要求了。因而就发明了线程,线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程能够有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。程序员
差异:1.线程是程序执行的最小单位,而进程是操做系统分配资源的最小单位;2.一个进程由一个或多个线程组成,线程是一个进程中代码的不一样执行路线;3.进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见;4.调度和切换:线程上下文切换比进程上下文切换要快得多。算法
联系:原则上一个CPU只能分配给一个进程,以便运行这个进程。一般使用的计算机中只有一个CPU,同时运行多个进程,就必须使用并发技术。一般采用时间片轮转进程调度算法,在操做系统的管理下,全部正在运行的进程轮流使用CPU,每一个进程容许占用CPU的时间很是短(好比10毫秒),这样用户根本感受不出来CPU是在轮流为多个进程服务,就好象全部的进程都在不间断地运行同样。但实际上在任何一个时间内有且仅有一个进程占有CPU。若是一台计算机有多个CPU,状况就不一样了,若是进程数小于CPU数,则不一样的进程能够分配给不一样的CPU来运行,这样,多个进程就是真正同时运行的,这即是并行。但若是进程数大于CPU数,则仍然须要使用并发技术。在Windows中,进行CPU分配是以线程为单位的,一个进程可能由多个线程组成。操做系统将CPU的时间片分配给多个线程,每一个线程在操做系统指定的时间片内完成(注意,这里的多个线程是分属于不一样进程的).操做系统不断的从一个线程的执行切换到另外一个线程的执行,如此往复,宏观上看来,就好像是多个线程在一块儿执行.因为这多个线程分属于不一样的进程,就好像是多个进程在同时执行,这样就实现了多任务。总线程数<=CPU数量时并行运行,总线程数>CPU数量时并发运行。并行运行的效率显然高于并发运行,因此在多CPU的计算机中,多任务的效率比较高。可是,若是在多CPU计算机中只运行一个进程(线程),就不能发挥多CPU的优点。数据库
● 请你说一下线程通讯的方法、线程的五种状态
参考回答:
线程通讯的方法:编程
①同步:多个线程经过synchronized关键字这种方式来实现线程间的通讯。安全
②while轮询的方式服务器
③wait/notify机制网络
④管道通讯就是使用java.io.PipedInputStream 和 java.io.PipedOutputStream进行通讯多线程
线程的五种状态:并发
1. 新建(NEW):新建立了一个线程对象。
2. 可运行(RUNNABLE):线程对象建立后,其余线程(好比main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
3. 运行(RUNNING):可运行状态(runnable)的线程得到了cpu 时间片(timeslice) ,执行程序代码。
4. 阻塞(BLOCKED):阻塞状态是指线程由于某种缘由放弃了cpu 使用权,也即让出了cpu timeslice,暂时中止运行。直到线程进入可运行(runnable)状态,才有机会再次得到cpu timeslice 转到运行(running)状态。阻塞的状况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其余阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程从新转入可运行(runnable)状态。
5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
● 请你说一下虚拟内存
参考回答:
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它一般是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在须要时进行数据交换
● 请你说一下线程的同步和互斥以及应用常见
参考回答:
互斥:指在某一时刻指容许一个进程运行其中的程序片,具备排他性和惟一性。
对于线程A和线程B来说,在同一时刻,只容许一个线程对临界资源进行操做,即当A进入临界区对资源操做时,B就必须等待;当A执行完,退出临界区后,B才能对临界资源进行操做。
同步:指的是在互斥的基础上,实现进程之间的有序访问。假设现有线程A和线程B,线程A须要往缓冲区写数据,线程B须要从缓冲区读数据,但他们之间存在一种制约关系,即当线程A写的时候,B不能来拿数据;B在拿数据的时候A不能往缓冲区写,也就是说,只有当A写完数据(或B取走数据),B才能来读数据(或A才能往里写数据)。这种关系就是一种线程的同步关系。
应用常见:多线程编程中,不免会遇到多个线程同时访问临界资源的问题,若是不对其加以保护,那么结果确定是不如预期的,所以须要线程同步与互斥。
● 请你说一下线程的五种状态以及转换
参考回答:
一、新生状态
在程序中用构造方法(new操做符)建立一个新线程时,如new Thread(r),该线程就是建立状态,此时它已经有了相应的内存空间和其它资源,可是尚未开始执行。
二、就绪状态
新建线程对象后,调用该线程的start()方法就能够启动线程。当线程启动时,线程进入就绪状态(runnable)。因为尚未分配CPU,线程将进入线程队列排队,等待 CPU 服务,这代表它已经具有了运行条件。当系统挑选一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态。系统挑选的动做称之为“CPU调度"。一旦得到CPU线程就进入运行状态并自动调用本身的run方法。
三、运行状态
当就绪状态的线程被调用并得到处理器资源时,线程就进入了运行状态。此时,自动调用该线程对象的run()方法。run()方法定义了该线程的操做和功能。运行状态中的线程执行本身的run方法中代码。直到调用其余方法或者发生阻塞而终止。
四、阻塞状态
一个正在执行的线程在某些特殊状况下,如被人为挂起或须要执行耗时的输入输出操做时,suspend()、 wait()等方法,线程都将进入堵塞状态。堵塞时,线程不能进入排队队列,只有当引发堵塞的缘由被消除后,线程转入就绪状态。重将让出 CPU 并暂时停止本身的执行,进入堵塞状态。在可执行状态下,若是调用 sleep()、 新到就绪队列中排队等待,这时被CPU调度选中后会从原来中止的位置开始继续执行。
五、死亡状态
线程调用stop()方法、destory()方法或 run()方法执行结束后,线程即处于死亡状态。处于死亡状态的线程不具备继续运行的能力。
● 请你说一说消息队列、信号量的实现方式
参考回答:
消息队列是消息的连接表,存储在内核中,由消息队列ID来标识。每一个队列都有一个msgid_ds结构与其相关联:
struct msgid_ds
{
struct ipc_perm msg_perm;
msgqnum_t msg_qnum; /* # of messages on queue */
msglen_t msg_qbytes; /* max # of bytes on queue */
pid_t msg_lspid; /* pid of last msgsnd() */
pid_t msg_lrpid; /* pid of last msgrcv() */
time_t msg_stime; /* last-msgsnd() time */
time_t msg_rtime; /* last-msgrcv() time */
time_t msg_ctime; /* last-change time */
...
};
此结构定义了队列的当前状态。msgget用于建立一个新队列或打开一个现有队列,msgsnd将消息添加到队列的尾端(每一个消息包括一个长整型类型字段,一个非负的长度,实际的数据长度),msgrcv用于从队列中取消息(并不必定要以先进先出次序取消息,能够按消息的类型字段取消息)。
信号量是一个计数器,用于为多个进程提供对共享对象的访问。为了正确地实现信号量,信号量的测试及加减1操做应当是原子操做,为此,信号量一般是在内核中实现的。
经常使用的信号形式是二元信号量(binary semaphore)。它控制单个资源,其初始值为1。可是,通常而言,信号量的初值也能够是任意一个正值,代表有多少个共享单位可供共享。
内核为每一个信号量集合维护着一个semid_ds结构:
struct semid_ds
{
struct ipc_perm sem_perm;
unsigned short sem_nsems; /* # of semaphores in set */
time_t sem_otime; /* last-semop() time */
time_t sem_ctime; /* last-change time */
...
};
每一个信号量由一个无名结构体表示,至少包含下列成员:
复制代码
1 2 3 4 5 6 7 8 |
|
● 请你说一下进程和线程的区别
参考回答:
进程:是具备必定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是能够独立运行的一段程序。
线程:是进程的一个实体,是CPU调度和分派的基本单位,比进程更小的能独立运行的基本单位,线程本身基本上不拥有系统资源,在运行时,只是暂用一些计数器、寄存器和栈 。线程有本身的堆栈和局部变量,但线程之间没有单独的地址空间。
一个程序至少有一个进程,一个进程至少有一个线程。
● 请你说一下死锁的概念、缘由、解决方法
参考回答:
一、死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其余进程所站用不会释放的资源而处于的一种永久等待状态。死锁的四个必要条件:
• 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
• 请求与保持条件(Hold and wait):已经获得资源的进程能够再次申请新的资源。
• 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
• 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每一个进程都在等待相邻进程正占用的资源。
java中产生死锁可能性的最根本缘由是:1)是多个线程涉及到多个锁,这些锁存在着交叉,因此可能会致使了一个锁依赖的闭环;2)默认的锁申请操做是阻塞的。
如,线程在得到一个锁L1的状况下再去申请另一个锁L2,也就是锁L1想要包含了锁L2,在得到了锁L1,而且没有释放锁L1的状况下,又去申请得到锁L2,这个是产生死锁的最根本缘由。
二、避免死锁:
• 方案一:破坏死锁的循环等待条件。
• 方法二:破坏死锁的请求与保持条件,使用lock的特性,为获取锁操做设置超时时间。这样不会死锁(至少不会无尽的死锁)
• 方法三:设置一个条件遍历与一个锁关联。该方法只用一把锁,没有chopstick类,将竞争从对筷子的争夺转换成了对状态的判断。仅当左右邻座都没有进餐时才能够进餐。提高了并发度。
● 请你说一下多线程
参考回答:
最开始,线程只是用于分配单个处理器的处理时间的一种工具。但假如操做系统自己支持多个处理器,那么每一个线程均可分配给一个不一样的处理器,真正进入“并行运算”状态。从程序设计语言的角度看,多线程操做最有价值的特性之一就是程序员没必要关心到底使用了多少个处理器。程序在逻辑意义上被分割为数个线程;假如机器自己安装了多个处理器,那么程序会运行得更快,毋需做出任何特殊的调校。根据前面的论述,你们可能感受线程处理很是简单。但必须注意一个问题:共享资源!若是有多个线程同时运行,并且它们试图访问相同的资源,就会遇到一个问题。举个例子来讲,两个线程不能将信息同时发送给一台打印机。为解决这个问题,对那些可共享的资源来讲(好比打印机),它们在使用期间必须进入锁定状态。因此一个线程可将资源锁定,在完成了它的任务后,再解开(释放)这个锁,使其余线程能够接着使用一样的资源。
多线程是为了同步完成多项任务,不是为了提升运行效率,而是为了提升资源使用效率来提升系统的效率。线程是在同一时间须要完成多项任务的时候实现的。
一个采用了多线程技术的应用程序能够更好地利用系统资源。其主要优点在于充分利用了CPU的空闲时间片,能够用尽量少的时间来对用户的要求作出响应,使得进程的总体运行效率获得较大提升,同时加强了应用程序的灵活性。更为重要的是,因为同一进程的全部线程是共享同一内存,因此不须要特殊的数据传送机制,不须要创建共享存储区或共享文件,从而使得不一样任务之间的协调操做与运行、数据的交互、资源的分配等问题更加易于解决。
● 请你说一下线程之间通讯的手段
参考回答:
使用全局变量
主要因为多个线程可能更改全局变量,所以全局变量最好声明为volatile
使用消息实现通讯
在Windows程序设计中,每个线程均可以拥有本身的消息队列(UI线程默认自带消息队列和消息循环,工做线程须要手动实现消息循环),所以能够采用消息进行线程间通讯sendMessage,postMessage。
使用事件CEvent类实现线程间通讯
Event对象有两种状态:有信号和无信号,线程能够监视处于有信号状态的事件,以便在适当的时候执行对事件的操做。
● 请你说一下死锁
参考回答:
一、死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其余进程所站用不会释放的资源而处于的一种永久等待状态。死锁的四个必要条件:
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(Hold and wait):已经获得资源的进程能够再次申请新的资源。
非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每一个进程都在等待相邻进程正占用的资源。
java中产生死锁可能性的最根本缘由是:1)是多个线程涉及到多个锁,这些锁存在着交叉,因此可能会致使了一个锁依赖的闭环;2)默认的锁申请操做是阻塞的。
如,线程在得到一个锁L1的状况下再去申请另一个锁L2,也就是锁L1想要包含了锁L2,在得到了锁L1,而且没有释放锁L1的状况下,又去申请得到锁L2,这个是产生死锁的最根本缘由。
二、避免死锁:
• 方案一:破坏死锁的循环等待条件。
• 方法二:破坏死锁的请求与保持条件,使用lock的特性,为获取锁操做设置超时时间。这样不会死锁(至少不会无尽的死锁)
• 方法三:设置一个条件遍历与一个锁关联。该方法只用一把锁,没有chopstick类,将竞争从对筷子的争夺转换成了对状态的判断。仅当左右邻座都没有进餐时才能够进餐。提高了并发度。
● 请你回答一下进程同步的方法
参考回答:
一、临界区(Critical Section):经过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
优势:保证在某一时刻只有一个线程能访问数据的简便办法
缺点:虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
二、互斥量(Mutex):为协调共同对一个共享资源的单独访问而设计的。
互斥量跟临界区很类似,比临界区复杂,互斥对象只有一个,只有拥有互斥对象的线程才具备访问资源的权限。
优势:使用互斥不只仅可以在同一应用程序不一样线程中实现资源的安全共享,并且能够在不一样应用程序的线程之间实现对资源的安全共享。
缺点:①互斥量是能够命名的,也就是说它能够跨越进程使用,因此建立互斥量须要的资源更多,因此若是只为了在进程内部是用的话使用临界区会带来速度上的优点并可以减小资源占用量。由于互斥量是跨进程的互斥量一旦被建立,就能够经过名字打开它。
②经过互斥量能够指定资源被独占的方式使用,但若是有下面一种状况经过互斥量就没法处理,好比如今一位用户购买了一份三个并发访问许可的数据库系统,能够根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操做,这时候若是利用互斥量就没有办法完成这个要求,信号量对象能够说是一种资源计数器。
三、信号量(Semaphore):为控制一个具备有限数量用户资源而设计。它容许多个线程在同一时刻访问同一资源,可是须要限制在同一时刻访问此资源的最大线程数目。互斥量是信号量的一种特殊状况,当信号量的最大资源数=1就是互斥量了。
优势:适用于对Socket(套接字)程序中线程的同步。(例如,网络上的HTTP服务器要对同一时间内访问同一页面的用户数加以限制,只有不大于设定的最大用户数目的线程可以进行访问,而其余的访问企图则被挂起,只有在有用户退出对此页面的访问后才有可能进入。)
缺点:①信号量机制必须有公共内存,不能用于分布式操做系统,这是它最大的弱点;
②信号量机制功能强大,但使用时对信号量的操做分散, 并且难以控制,读写和维护都很困难,加剧了程序员的编码负担;
③核心操做P-V分散在各用户程序的代码中,不易控制和管理,一旦错误,后果严重,且不易发现和纠正。
四、事件(Event): 用来通知线程有一些事件已发生,从而启动后继任务的开始。
优势:事件对象经过通知操做的方式来保持线程的同步,而且能够实现不一样进程中的线程同步操做。
● 请问进程线程的区别,进程间怎么相互通讯,什么是多线程,什么是并发
参考回答:
进程和线程的区别有如下几点
一、进程是资源分配的最小单位,线程是程序执行的最小单位
二、进程有本身独立地址空间,每启动一个进程,系统就会为它分配地址空间,创建数据表来维护代码段,堆栈段,数据段,而线程是共享进程中的数据的,使用相同的地址空间,可是CPU切换一个线程的花费远比进程要小,
三、线程之间通讯方式更方便,同一进程下的线程共享全局变量等数据,而进程之间的通讯方式须要以通讯的方式进行,
四、多线程程序中只要有一个线程死掉了,整个进程也死掉了,而一个进程死掉了,并不会对另外一个进程形成影响,由于进程有本身独立的地址空间
进程间的通讯方式:
一、无名管道通讯,数据只能单向流动,只能在具备亲缘的进程间使用
二、高级管道通讯,将领一个程序看成一个新的进程在当前程序中启动,则他算是当前进程的子进程
三、有名管道通讯,容许无亲缘关系进程间的通讯
四、消息队列通讯,消息队列是由消息的链表,存放在内核中并由消息队列标识符标识,消息队列克服了信息传递信息少等缺点
五、信号量通讯,信号量用于控制多个进程对共享资源的访问
六、信号通讯,用于通知接受进程某个事件已经发生
七、共享内存通讯,共享内存映射一段能被其余进程所访问的内存,每每与其余通讯机制配合使用,来实现进程间的同步和通讯
八、套接字通讯,他用于不一样机器之间的进程通讯
什么是多线程
多线程就是指一个进程中同时有多个执行路径正在执行
并发指在操做系统中,一个时间段中有几个程序都已处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上面,但任意时刻点上只有一个程序在处理机上运行。