一分钟明白进程,线程及线程安全和线程不安全,死锁

进程
进程的概念
  • 进程的起源和描述:在多道程序环境下,允许多个程序并发执行,此时它们将失去封闭性,并具有间断性及不可再现性的特征。为此引入了进程(Process)的概念,以便更好地描述和控制程序的并发执行,实现操作系统的并发性和共享性。
  • 相应的数据结构:PCB
  • 进程实体(进程映像)包括三部分:程序段,相关数据段和pcb段;
  • PCB块的作用:使得上面提到的程序成为一个能独立运行的基本单位,也就是进程 ,可以与其他进程并发执行的进程;OS是根据PCB来对并发执行的进程进行控制和管理的。
  • PDC块记录的内容有哪些:(首先有一些基本信息:例如进程名字,进程相对应的程序和数据的地址 ,进程拥有的资源清单;进程当前状态;关于进程调度的:进程优先级,进程调度时的cpu线程保护信息)
    1. 进程标识符 name:每个进程都必须有一个唯一的标识符,可以是字符串,也可以是一个数字。
    2. 进程当前状态 (新建态、终止态,运行态,就绪态,阻塞态(又称等待状态)):相同状态的进程会放在同一个队列中
    3. 进程相应的程序和数据地址,以便把PCB与其程序和数据联系起来。
    4. 进程资源清单。列出所拥有的除CPU外的资源记录,如拥有的I/O设备,打开的文件列表等。
    5. 进程优先级 priority:进程的优先级反映进程的紧迫程度,通常由用户指定和系统设置。
    6. CPU现场保护区 cpustatus:当进程因某种原因不能继续占用CPU时(如等待打印机),释放CPU,这时就要将CPU的各种状态信息保护起来,为将来再次得到处理机恢复CPU的各种状态,继续运行。
    7. 进程同步与通信机制 用于实现进程间互斥、同步和通信所需的信号量等
    8. 进程所在队列PCB的链接字 根据进程所处的现行状态,进程相应的PCB参加到不同队列中。PCB链接字指出该进程所在队列中下一个进程PCB的首地址。
    9. 与进程有关的其他信息。 如进程记账信息,进程占用CPU的时间等
  • PCB工作实例
    例如,当OS要调度某进程执行时,要从该进程的PCB中查处其现行状态优先级;在调度到某进程后,要根据其PCB中所保存的处理机状态信息,设置该进程恢复运行的现场,并根据其PCB中的程序和数据的内存始址,找到其程序和数据;进程在执行过程中,当需要和与之合作的进程实现同步,通信或者访问文件时,也都需要访问PCB;当进程由于某种原因而暂停执行时,又须将器断点的处理机环境保存在PCB中。可见,在进程的整个生命期中,系统总是通过PCB对进程进行控制的,即系统是根据进程的PCB而不是任何别的什么而感知到该进程的存在的。所以说,PCB是进程存在的唯一标志。
进程的经典定义

从不同的角度,进程可以有不同的定义,比较典型的定义有:

  • 进程是程序的一次执行过程。
  • 进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
  • 进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。

进程的特征

进程是由多程序的并发执行而引出的,它和程序是两个截然不同的概念。进程的基本特征是对比单个程序的顺序执行提出的,也是对进程管理提出的基本要求。

  • 动态性:进程是程序的一次执行,它有着创建、活动、暂停、终止等过程,具有一定的生命周期,是动态地产生、变化和消亡的。动态性是进程最基本的特征。
  • 并发性:指多个进程实体,同存于内存中,能在一段时间内同时运行,并发性是进程的重要特征,同时也是操作系统的重要特征。引入进程的目的就是为了使程序能与其他进程的程序并发执行,以提高资源利用率。
  • 独立性:指进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位。凡未建立PCB的程序都不能作为一个独立的单位参与运行。
  • 异步性:由于进程的相互制约,使进程具有执行的间断性,即进程按各自独立的、 不可预知的速度向前推进。异步性会导致执行结果的不可再现性,为此,在操作系统中必须配置相应的进程同步机制。
  • 结构性:每个进程都配置一个PCB对其进行描述。从结构上看,进程实体是由程序段、数据段和进程控制段三部分组成的。
进程状态:

请添加图片描述
进程在其生命周期内,由于系统中各进程之间的相互制约关系及系统的运行环境的变化,使得进程的状态也在不断地发生变化(一个进程会经历若干种不同状态)。通常进程有以下五种状态,前三种是进程的基本状态。

  • 运行状态(RUNNING):进程正在处理机上运行。在单处理机环境下,每一时刻最多只有一个进程处于运行状态。

  • 就绪状态(READY):进程已处于准备运行的状态,即进程获得了除处理机之外的一切所需资源,一旦得到处理机即可运行。

  • 阻塞状态(BLOCKED),又称等待状态:进程正在等待某一事件而暂停运行,如等待某资源为可用(不包括处理机)或等待输入/输出完成。即使处理机空闲,该进程也不能运行。进入阻塞状态的进程会释放掉处理机资源,进入阻塞队列,直到在阻塞队列中排队获取到了临界资源,重新进入就绪队列;

  1. 阻塞原语的执行过程是:
    ①找到将要被阻塞进程的标识号对应的PCB。
    ②若该进程为运行状态,则保护其现场,将其状态转为阻塞状态,停止运行。
    ③把该PCB插入到相应事件的等待队列中去。

    当被阻塞进程所期待的事件出现时,如它所启动的I/O操作已完成或其所期待的数据已到达,则由有关进程(比如,提供数据的进程)调用唤醒原语(Wakeup),将等待该事件的进程唤醒。

  2. 唤醒原语的执行过程是:
    ①在该事件的等待队列中找到相应进程的PCB。
    ②将其从等待队列中移出,并置其状态为就绪状态。
    ③把该PCB插入就绪队列中,等待调度程序调度。

  • 创建状态(NEW):进程正在被创建,尚未转到就绪状态。创建进程通常需要多个步骤:首先申请一个空白的PCB,并向PCB中填写一些控制和管理进程的信息;然后由系统为该进程分配运行时所必需的资源;最后把该进程转入到就绪状态。

  • 结束状态(TERMINATED):进程正从系统中消失,这可能是进程正常结束或其他原因中断退出运行。当进程需要结束运行时,系统首先必须置该进程为结束状态,然后再进一步处理资源释放和回收等工作。

  • WAITING状态是:“一个线程在等待另一个线程执行一个动作时在这个状态”,这是一个死等的过程,直到被其他线程唤醒重新进入RUNABLE状态;
    进入WAITING状态的方式有:

  1. 同步代码块中调用对象的.wait()方法;
    注意事项:
    1>wait被调用之前notify的唤醒通知就来了,那么这个线程并不能保证被唤醒,有可能会导致死锁问题
    2>notify方法会随机唤起一个线程,推荐使用notifyall()
public class WaitNotify {
    static class WaitClass implements Runnable {
        @Override
        public void run() {
            synchronized (WaitNotify.class) {
                System.out.println("进入wait");
                try {
                //调用wait()方法的对象,必须和锁对象一致;调用wait方法,线程会释放同步锁,从而其他线程可以使用notify;
                    WaitNotify.class.wait();
                    System.out.println("被唤醒了");
                } catch (InterruptedException e) {
                }
            }
        }
    }

    static class NotifyClase implements Runnable {
        @Override
        public void run() {
            synchronized (WaitNotify.class) {
                System.out.println("唤醒它");
                try {
                //唤醒在WaitNotify.class(这个临界资源)上wait的线程
                    WaitNotify.class.notifyAll();
                    System.out.println("醒了");
                } catch (Exception e) {
                }
            }
        }
    }

    public static void main(String[] args) {
        new Thread(new WaitClass()).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        new Thread(new NotifyClase()).start();
    }
}
  • TIMED_WAITING状态为:“一个线程在一个特定的等待时间内等待另一个线程完成一个动作会在这个状态”
    Thread. sleep(long millis);不会释放锁,sleep时间结束后会自动唤醒进入READY状态,获取到处理机后进入RUNNING状态;
    native void wait(long timeout);会释放锁,时间结束后,需要重新获取锁对象;分两种情况:一是立即获取到了锁,线程自然会继续执行(进入READY状态);二是没有立即获取锁,线程进入同步队列等待获取锁(BLOCKED);
    Java中如何唤醒“指定的“某个线程
线程
  • 进程的起源和描述:线程的引入主要是为了提高并发性能,进程的调度往往开销是比较大的,所以将进程当作线程的一个容器,以进程作为操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位,也就是说线程是进程实际运行的实体,线程也有轻量级进程的说法;
  • 线程的组成:线程ID、程序计数器、寄存器集合和堆栈组成。线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。
  • 由于同一进程的各线程间共享内存和文件资源,可以不通过内核进行直接通信 ,一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。
并行和并发:
线程安全:

线程安全就是在多线程编程中通过一些同步机制保证各个线程都可以正常且正确的执行;当然要回答好这个问题还得从它的反面线程不安全说起,那么什么是线程不安全呢? ——是指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

  • 线程安全之所以成为问题是由于:
    原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行
    可见性:层次化存储,为了综合访问存储的速度、容量、价格,现代计算机通常采用 Cache、主存、外存的层次化存储。
    重排序:为了提高 CPU 的吞吐率,通常会通过乱序技术把“无关”的指令在不同流水线上。(编译器,cpu,JIT)

    1. 使用没有共享资源的模型
    2. 适用共享资源只读,不写的模型
      1. 不需要写共享资源的模型
      2. 使用不可变对象
    3. 直面线程安全(重点)
      1. 保证原子性
      2. 保证顺序性
      3. 保证可见性
  • 让一个类或者函数线程安全有两种方法:
    加锁,锁可以让乱序变的有序;锁还可以触发“回写”,让 Cache 和内存保持一致;
    复制,每个线程一份数据,不共享数据;

死锁

进程的并发执行,改善了系统资源的利用率并提高了系统 的处理能力。然而,多个进程的并发执行也带来了新的问题——死锁。所谓死锁是指多个进 程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
死锁产生的必要条件

产生死锁的条件

必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生

  • 互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
  • 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
  • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
  • 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。即存在一个处于等待状态的进程集合{Pl, P2, …, pn},其中Pi等 待的资源被P(i+1)占有(i=0, 1, …, n-1),Pn等待的资源被P0占有;
  • 解决死锁的策略在这里插入图片描述

参考文献:
[1] C语言中文网 进程的概念

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值