常见问题
全是从面经里扒拉出来的面试题
进程和线程
进程:资源分配的基本单位,一个进程中可以有多个线程,它们共享进程资源,线程不拥有资源,线程可以访问隶属进程的资源。
线程:独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换。
系统开销 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。
类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置。
而线程切换时只需保存和设置少量寄存器内容,开销很小。
通信方面 线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。
为什么有进程还要线程:减少程序在并发执行时所付出的时空开销,提高并发性。
进程间通信
类似问题:
操作系统中有哪些跨进程通信(IPC)的方法
进程通信的六种方式:管道、FIFO、消息队列、信号量、共享存储、套接字。
管道:速度慢,容量有限,只有父子进程能通讯。管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
FIFO:任何进程间都能通讯,但速度慢。FIFO是一种半双工的通信方式,但是它允许无亲缘关系进程间的通信。
消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号量:不能传递复杂消息,只能用来同步。信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
套接字Socket:套接口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
消息队列对比管道、FIFO的优点:
消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;
读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收。
进程同步
进程同步:控制多个进程按一定顺序执行
进程通信:进程间传输信息
线程通信
方式一:使用 volatile 关键字。使用共享内存的思想,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式。
方式二:使用 Object 类的wait()、notify() 和 notifyaAlL(),它们是多线程通信的基础,而这种实现方式的思想自然是线程间通信。
注意:wait() 和 notify() 必须配合 synchronized 使用。
调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。它们都属于 Object 的一部分,而不属于 Thread。只能用在同步方法或者同步控制块中使用,否则会在运行时抛出IllegalMonitorStateException。使用 wait() 挂起期间,线程会释放锁。这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,那么就无法执行 notify() 或者 notifyAll() 来唤醒挂起的线程,造成死锁。
线程安全
Java
保证线程安全可从多线程三特性出发:
原子性(Atomicity):单个或多个操作是要么全部执行,要么都不执行
Lock:保证同时只有一个线程能拿到锁,并执行申请锁和释放锁的代码
synchronized:对线程加独占锁,被它修饰的类/方法/变量只允许一个线程访问
原子性就是说一个操作不可以被中途cpu暂停然后调度,即不能被中断,要不就执行完,要不就不执行。如果一个操作是原子性的,那么在多线程环境下,就不会出现变量被修改等奇怪的问题。
可见性(Visibility):当一个线程修改了共享变量的值,其他线程能够立即得知这个修改
volatile:保证新值能立即同步到主内存,且每次使用前立即从主内存刷新;
synchronized:在释放锁之前会将工作内存新值更新到主存中
有序性(Ordering):程序代码按照指令顺序执行
volatile: 本身就包含了禁止指令重排序的语义
synchronized:保证一个变量在同一个时刻只允许一条线程对其进行lock操作,使得持有同一个锁的两个同步块只能串行地进入
一定有线程吗?为什么要有线程?
类似问题:
操作系统一定有线程吗?
为什么要有线程
谈谈对操作系统中的进程的理解
线程和进程的同步机制和通信机制
进程的内存布局,哪些是线程共享
进程与线程的切换开销
进程同步
进程调度算法
进程调度的策略,现在的OS主要是什么策略
进程内部和进程之间如何处理同一个文件
线程调度的方式
什么是缓存溢出
并发和并行分别是什么意思,多线程是并发还是并行
单CPU能实现多任务并行吗
CPU 调度算法
类似问题:
CPU 调度算法,多核的情况下,操作系统怎么处理
为什么有多进程也有多线程
扯到了虚拟内存空间,面试官就问为什么要这样设计?解决什么问题?
操作系统的内存管理
分页分段段页式
虚拟内存和物理内存的区别
假如手机只有10M内存,想要申请1M的内存是否一定成功
内存分布
什么是虚拟内存、共享内存、物理内存
虚拟内存的作用
说说共享内存的原理
分页分段管理
分段和分页有什么区别
页一般多大
中断
类似问题:
中断是什么,Linux的中断命令
中断是怎么实现的
linux 崩溃中断
解释一下中断
操作系统有哪些算法支持高效的内存的申请与释放,同时最大化的减少碎片
zero-copy 与 copy-on-write(COW);
地址空间的概念
指针能不能访问0x0
如何在进程中直接操作物理地址
计算机寻址的方式
直接寻址和间接寻址谁更安全
为什么要分用户态、内核态
类似问题:
用户态/内核态
内核态、用户态相关,扯了几句异常控制流
时间片
4个CPU,16个数,每个CPU每次只能比较一次两个数的大小,只能返回
true
或false
,互相之间不能通信,一轮以时间片为单位,需要几轮能够找出最大的数(4个CPU与4个数,可以一轮就找到最大的数吗)
死锁以及如何避免死锁
类似问题:
死锁的四个条件,开发过程中什么情况容易造成死锁
多线程访问堆段会出现什么问题,如何解决这些问题
(信号量、锁)
堆和栈的区别
生产者-消费者模型,其中的同步机制是怎么样的
读者写者模型
类似问题:
读者-写者问题
什么是抢占
程序崩溃
多线程会不会导致程序崩溃,程序会因为什么崩溃,子线程崩了的话进程会不会崩?(如果捕获了异常或信号就不会崩)
什么情况下会stackoverflow
操作系统的锁底层如何实现
知道哪些锁,说说它们的区别
什么是互斥锁/读写锁
类似问题:
什么场景用互斥锁,什么场景用读写锁
文件I/O的过程
什么是写优先和读写平衡
大小端
最后更新于