操作系统的几个问题
1、进程和线程的区别?
解析:
(1)进程是资源分配和调度的一个独立单元,而线程是CPU调度的基本单元;
(2)同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程;
(3)进程的创建调用fork或者vfork,而线程的创建调用pthread_create,进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束;
(4)线程是轻量级的进程,它的创建和销毁所需要的时间比进程小很多,所有操作系统中的执行功能都是创建线程去完成的;
(5)线程在执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源;
(6)线程有自己的私有属性TCB,线程id,寄存器、硬件上下文,而进程也有自己的私有属性进程控制块PCB,这些私有属性是不被共享的,是用来标识一个进程或一个线程的标志。
2、死锁?死锁产生的原因?死锁的必要条件?怎么处理死锁?
解析:
死锁:死锁是相互等待资源而产生的一种僵持状态,如果没有外力的干预将一直持续这个状态;
死锁产生的原因:系统资源不足、相互竞争资源、请求资源顺序不当;
死锁的必要条件:互斥、不可抢占、循环等待、请求与保持;
处理死锁:因为互斥是不可改变的,所以只能破坏其他三个条件中的一个来解除死锁,方法:剥夺资源、杀死其中一个线程。
3、Windows内存管理方式有哪些?
解析:段存储、页存储、段页存储。
4、进程的几种状态?
解析:
(1)run(运行状态):正在运行的进程或在等待队列中等待的进程,等待的进程只要得到cpu就可以运行;
(2)Sleep(可中断休眠状态):相当于阻塞或在等待的状态;
(3)D(不可中断休眠状态):在磁盘上的进程;
(4)T(停止状态):这种状态无法直观的看见,因为是进程停止后就释放了资源,所以不会留在linux中;
(5)Z(僵尸状态):子进程先与父进程结束,但父进程没有调用wait或waitpid来回收子进程的资源,所以子进程就成了僵尸进程,如果父进程结束后仍然没有回收子进程的资源,那么1号进程将回收。
5、IPC通信方式?
解析:
(1)管道(匿名管道(pipe亲缘关系的进程通信)、命名管道(mkfifo/mknod));
(2)消息队列:是基于消息的、用无亲缘关系的进程间通信,主要函数:msgget、msgsend、msgrecv、msgctl;
(3)信号量:相当于一把互斥锁,通过p、v操作,主要函数:semget、semop、semctl;
(4)共享内存:是进程间通信速度最快的,所以用经常是集合信号量或互斥锁来实现同步,shmget、shmat、shmdt、shmctl。
6、什么是虚拟内存?
解析:是将进程部分装入内存中,从而能实现一个很大的程序能在一个比它小的内存中运行,它的主要实现是靠程序的换进换出来实现的,因为内存中0~3G是用户使用,3~4G才是内存使用,通过映射来实现来进行逻辑地址到物理地址的映射。
7、虚拟地址、逻辑地址、线性地址、物理地址的区别?
解析:分段机制把一个逻辑地址转换为线性地址;接着,分页机制把一个线性地址转换为物理地址。
(1)虚拟地址:虚拟内存映射出来的地址;
(2)逻辑地址:程序的段加偏移量形成的,C/C++程序中取地址求出来的地址就是逻辑地址;
(3)线性地址:是逻辑地址到物理地址的中间层,只有启动分页机制的时候才有线性地址,如果没有分页机制,那么线性地址就是物理地址;
(4)物理地址:是内存中实实在在存在的硬件地址。
逻辑地址(启动分段)-->线性地址(启动分页)-->物理地址
8、同步和异步有何异同,在什么情况下分别使用他们?
解析:
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步才能保证存取正确性,这时候就应该使用同步编程;当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回结果时,这时候就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
Java中关于线程的几个问题
1、多线程有几种实现方法?同步有几种实现方法?
解析:
多线程有两种实现方法,分别是继承Thread类与实现Runnable接口。
同步的实现有两种方法,分别是synchronized,wait与notify。
wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException(中断异常)异常。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
Allnotity():唤醒所有处于等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
2、启动一个线程是用run()还是start()?
解析:
启动一个线程是调用start()方法,使线程处于就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码才有意义,run()方法是该线程所关联的执行代码。
3、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
解析:分以下几种情况:
(1)其他方法前是否加了synchronized关键字,如果没加,则能;
(2)如果这个方法内部调用了wait,则可以进入其他synchronized方法;
(3)如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能;
(4)如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。
4、线程的基本概念、线程的基本状态以及状态之间的关系?
解析:一个程序中可以有多条执行线索同时执行,一个线程就是程序中的一条执行线索,每个线程上都关联有要执行的代码,即可以有多段程序代码同时运行,每个程序至少都有一个线程,即main方法执行的那个线程。如果只是一个cpu,它怎么能够同时执行多段程序呢?这是从宏观上来看的,cpu一会儿执行a线索,一会儿执行b线索,切换时间很快,给人的感觉好像是a,b在同时执行,好比大家在同一个办公室上网,只有一条链接到外部的网线,其实,这条网线一会为a传数据,一会为b传数据,由于切换时间很短暂,所以,大家感觉都在同时上网。
状态:就绪,运行,synchronize阻塞,wait和sleep挂起,结束。wait必须在synchronized内部调用。
调用线程的start方法后线程进入就绪状态,线程调度系统将就绪状态的线程转为运行状态,遇到synchronized语句时,由运行状态转为阻塞状态,当synchronized获得锁后,由阻塞状态转为运行状态,在这种情况可以调用wait方法转为挂起状态,当线程关联的代码执行完后,线程变为结束状态。
5、简述synchronized和java.util.concurrent.locks.Lock的异同?
解析:
主要相同点:Lock能完成synchronized所实现的所有功能。
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以以非阻塞方式去拿锁。