操作系统
进程与线程
-
进程 (Process)
- 定义:进程是操作系统中一个独立的运行实体,它拥有自己的独立的地址空间、代码、数据和系统资源。换句话说,进程是一个正在执行的程序的实例。
- 资源隔离:每个进程都有其独立的内存地址空间,所以一个进程崩溃不会影响其他进程。
- 创建开销:创建和销毁进程通常都需要相对较大的开销。
- 通信方式:进程间的通信(IPC)需要特定的机制,如管道、消息队列、共享内存等。
-
线程 (Thread)
- 定义:线程也被称为轻量级进程,它是进程内部的执行单元。一个进程可以包含多个线程,这些线程共享该进程的地址空间和资源。
- 资源共享:同一进程中的线程共享相同的地址空间和资源,因此它们之间的通信更为简单。但这也意味着一个线程崩溃可能会影响同一进程中的其他线程。
- 创建开销:相较于进程,线程的创建和销毁开销较小。
- 通信方式:由于同一进程的线程共享内存,它们可以直接读取和写入共享数据。但这也引入了并发控制的问题,比如需要使用锁来避免数据不一致和冲突。
对比与关系:
- 进程为资源分配的基本单位,线程为CPU调度的基本单位。
- 一个进程可以拥有多个线程,线程间共享进程的资源。
- 进程间是相互独立的,而同一进程中的多个线程是相互依赖的。
- 进程间的切换开销远大于线程间的切换开销。
理解这两者的关系和差异对于深入理解并发编程和操作系统的原理是非常重要的。
死锁(Deadlock)是指两个或多个进程在执行过程中,因争夺资源而造成的一种相互等待的现象,若无外力干涉那它们都无法再向前进行。
死锁
死锁通常发生在多任务环境中,当多个进程/线程尝试按照不同的顺序获得多个资源时,可能会发生死锁。
为了更好地理解,让我们使用一个简单的例子:假设有两个进程A和B,以及两个资源X和Y。进程A持有资源X并等待资源Y,同时进程B持有资源Y并等待资源X。在这种情况下,没有进程能够继续执行,因为它们都在等待另一个进程释放所需的资源。
发生死锁的四个必要条件:
- 互斥条件:资源不可被共享,一次只有一个进程可以使用资源。
- 请求与保持条件:进程在持有至少一个资源的情况下,又提出了新的资源请求,而该资源已被其他进程占用,所以该进程会等待,但在等待的同时,它不会释放其已占有的资源。
- 不剥夺条件:已经分配给进程的资源在未使用完之前,不能被剥夺,只能由该进程自己释放。
- 循环等待条件:存在一组等待进程,其中每个进程都在等待下一个进程所持有的资源。
避免或处理死锁的策略有很多,包括死锁预防、死锁避免和死锁检测与恢复。常用的算法和技术有银行家算法、资源有序分配法等。
题目
如何在多线程中避免发生死锁 .
a) 允许进程同时访问某些资源。(√)
b) 允许进程强行从占有者那里夺取某些资源。(√)
c) 进程在运行前一次性地向系统申请它所需要的全部资源。(√)
d) 把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。 (√)
问题:下列哪些操作会使线程释放锁资源? (考察释放锁资源)
a) sleep()
b) wait() (√)
c) join() (√)
d) yield()
释放锁资源:通知对象内置的monitor对象进行释放,所以前提是:所有对象都有内置的monitor对象;
所有类都继承自Object,所以wait()就成了Object方法,即通过wait()来通知对象内置的monitor对象释放;而且事实上因为这涉及对硬件底层的操作,所以wait()方法是native方法,底层是用C写的。
其他都是Thread所有,所以其他3个是没有资格释放资源的
join()有资格释放资源其实是通过调用wait()来实现的
- sleep()方法
- 在指定时间内让当前正在执行的线程暂停执行,进入阻塞状态,但不会释放“锁标志”。不推荐使用。
- wait()方法
- 在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。
- 当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。
- 唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。
- waite()和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。
- yield()方法
- 暂停当前正在执行的线程对象。
- 只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
- 只能使同优先级或更高优先级的线程有执行的机会。
- join()方法
- 等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测
Linux文件权限
文件目录data当前权限为rwx --- ---,只需要增加用户组可读权限,但不允许写操作,具体方法为
要为目录 data
增加用户组的读权限(而不添加写权限),你需要使用 chmod
命令,并为用户组设置读权限位。
在这种情境下,你应该使用:
chmod +040 data
解释:
- 用户权限用三个数字表示:用户(u)、用户组(g)、其他用户(o)。
- 每个数字是三个权限(读、写、执行)的二进制表示。
- 读(r):4
- 写(w):2
- 执行(x):1
在这里,你想为用户组(g)添加读(r)权限,所以是040
。
计算机中的最小单位是位,最小存储单位是字节
执行以下shell语句,可以生成/test文件的是(假定执行前没有/test文件):
A touch /test
B a=touch /test
C >/test
D echo 'touch /test'
B选项,不是单引号,而是反单引号,a=touch /test
表示执行 touch /test 并将结果返回给a