3

进程通信

进程间的信息交换,具体内容分为:控制信息交换和数据交换,控制信息的交换为低级通信,数据的交换为高级通信。

高级通信方式

  • 共享存储系统

多台服务器访问同一个存储设备的同一分区

  • 消息传递系统

进程与其它的进程进行通信而不必借助共享数据,通过互相发送和接收消息,建立一条通信链路。

  • 管道通信

发送进程以字符流形式将大量数据送入管道,接收进程可从管道接收数据,二者利用管道进行通信,管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起。一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据。每次只有一个进程能够真正地进入管道,其他的只能等待。

管道分为无名管道和命名管道,前者用于父子进程通信,后者用于任意进程通信。

无名管道由pipe( )函数创建:int pipe(int filedis[2])当一个管道被创建时,它会创建两个文件描述符:filedis[0]用于读管道,filedis[1]用于写管道

关闭管道只是将两个文件描述符关闭即可,可以使用普通的close函数逐个关闭。

管道的形式:

进程调度

进程调度就是处理器调度(上下文切换)

调度级别

  • 高级调度

作业调度,把后备作业调入内存运行

  • 中级调度

在虚拟存储器中引入,在内,外存交换区进行进程对换

  • 低级调度

进程调度,把就绪队列里的某个进程获得CPU执行权

调度方式

  • 可剥夺

当一个进程运行时,基于某种原则,剥夺已经分配给它的处理器,将之分配给其他进程,原则有:优先权原则,短进程优先原则,时间片原则。

  • 不可剥夺

一单处理器分配给某进程,遍让它一直运行下去,直到进程完成或者发生某种时间而阻塞,才分配给其他进程。

调度算法

  • 先进先出

按照进入就绪队列的进程顺序,不加其他条件干涉

  • 短进程优先

优先选出就绪队列中CPU执行时间最短的进程,例如:就绪队列有4个进程P1,P2,P3,P4,执行时间为:16,12,4,3 按照短进程优先,则周转时间(从进程提交到进程完成的时间间隔)分别为:35,19,7,3
平均周转时间:16,平均周转时间越小,调度性能越好

  • 轮转法

    • 简单轮转: 就绪进程按FIFO排队,按照一定时间间隔让处理机分配给队列中的进程,就绪队列中所有队列均可获得一个时间片的处理器运行

    • 多级队列: 让系统中所有进程分成若干类,每类一级

死锁

两个以上的进程相互请求对方已经占有的资源,导致无限期的等待。

产生条件

  • 互斥条件

  • 请求保持

  • 不可剥夺

  • 环路条件

解决方法

  • 鸵鸟策略:不理睬

  • 预防策略:破坏产生条件中任意一个

  • 避免策略: 精心分配资源,动态避免死锁

  • 检测与解除死锁:系统自动检测,并且解除

线程

来源

  • 由于之前进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程

  • 对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。

有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元,一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,线程也有就绪、阻塞和运行三种基本状态,每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身

包含

  • 程序

  • 数据(堆栈(系统栈或用户栈)寄存器)

寄存器可被用来存储线程内的局部变量,但不能存储其他线程的相关变量

  • TCB

TCB包含 1.线程状态 2.线程不可运行时,被保存的现场资源 3.一组执行堆栈 4.存放每个线程的局部变量主存区 5.访问同一个进程中的主存和其他资源

特点

  • 轻量 切换非常快

  • 独立调度和分派的基本单位

  • 并发执行 不同进程中的线程也可以并发执行

  • 共享进程资源 所有线程具有相同的地址空间,线程可以访问线程已经拥有的已打开文件,定时器,信号量,由于一个进程中的线程共享内存和文件,所以线程之间的相同通信不必调用内核

线程之间的通信可以通过进程(数据段)的全局变量完成,线程是进程中的实体,线程有它自己的堆栈、自己的程序计数器和自己的局部变量,与分隔的进程相比,进程中的线程之间的隔离程度要小。它们共享内存、文件句柄和其它每个进程应有的状态。

Java线程状态

  • 新线程态(New Thread)

当线程处于"新线程"状态时,仅仅是一个空线程对象,它还没有分配到系统资源。因此只能启动或终止它。任何其他操作都会引发异常。一个线程调用了new方法之后,并在调用start方法之前的处于新线程状态,可以调用start和stop方法。

  • 可运行态(Runnable)

start()方法产生运行线程所必须的资源,调度线程执行,如果线程处于Runnable状态,它也有可能不在运行,这是因为还有优先级和调度问题。

  • 阻塞/非运行态

    • suspend()方法被调用

    • sleep()方法被调用

    • wait()来等待条件变量

    • 线程处于I/O请求的等待

  • 死亡态

当run()方法返回,或别的线程调用stop()方法,线程进入死亡态,一个线程执行结束,它的寄存器上下文以及堆栈内容等将被释放。

Java中线程

Java采用的是一种简单、固定的调度法,即固定优先级调度,线程组是让多个线程集于一个对象中,可以对这些线程进程批量操作,一单加入了某个线程组,就不能移除。Java并不提供对死锁的检测机制,Java的多线程安全是基于Lock机制实现的,而Lock的性能往往不如人意。原因是,monitorenter与monitorexit这两个控制多线程同步的bytecode原语,是JVM依赖操作系统互斥(mutex)来实现的。而互斥是一种会导致线程挂起,并在较短的时间内又需要重新调度回原线程的,较为消耗资源的操作。所以需要进行对线程进行优化,提高效率。


感谢您的耐心阅读,如果您发现文章中有一些没表述清楚的,或者是不对的地方,请给我留言,你的鼓励是作者写作最大的动力,
如果您认为本文质量不错,读后觉得收获很大,不妨小额赞助我一下,让我更有动力继续写出高质量的文章。

  • 支付宝

  • 微信

作 者 : @mousycoder

原文出处 : http://mousycoder.com/2015/10/14/the-pragmatic-sa-16/

创作时间:2015-9-14

更新时间:2015-10-16


mousycoder
5.4k 声望819 粉丝

引用和评论

0 条评论