常见问题
全是从面经里扒拉出来的面试题
最后更新于
这有帮助吗?
进程:资源分配的基本单位,一个进程中可以有多个线程,它们共享进程资源,线程不拥有资源,线程可以访问隶属进程的资源。
线程:独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换。
系统开销 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、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操作,使得持有同一个锁的两个同步块只能串行地进入
类似问题:
操作系统一定有线程吗?
为什么要有线程
类似问题:
CPU 调度算法,多核的情况下,操作系统怎么处理
扯到了虚拟内存空间,面试官就问为什么要这样设计?解决什么问题?
分页分段段页式
类似问题:
中断是什么,Linux的中断命令
中断是怎么实现的
linux 崩溃中断
解释一下中断
zero-copy 与 copy-on-write(COW);
类似问题:
用户态/内核态
内核态、用户态相关,扯了几句异常控制流
4个CPU,16个数,每个CPU每次只能比较一次两个数的大小,只能返回
true
或false
,互相之间不能通信,一轮以时间片为单位,需要几轮能够找出最大的数(4个CPU与4个数,可以一轮就找到最大的数吗)
类似问题:
死锁的四个条件,开发过程中什么情况容易造成死锁
(信号量、锁)
类似问题:
读者-写者问题
多线程会不会导致程序崩溃,程序会因为什么崩溃,子线程崩了的话进程会不会崩?(如果捕获了异常或信号就不会崩)
类似问题:
什么场景用互斥锁,什么场景用读写锁