操作系统
死锁
定义: 是进程死锁的简称,指多个进程循环等待它方占有的资源而无限期僵持下去的局面。
// 死锁样例
class HoldLockThread implements Runnable{
private String a;
private String b;
public HoldLockThread(String a, String b) {
this.a = a;
this.b = b;
}
@Override
public void run() {
synchronized (a){
System.out.println(Thread.currentThread().getName()+ " 持有A锁,想要获得B锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b){
System.out.println(Thread.currentThread().getName()+ " 持有B锁,想要获得A锁");
}
}
}
}
public class DeadLockDemo {
public static void main(String[] args) {
String a = "lockA";
String b = "lockB";
// 线程1持有a锁,想要获取b锁
new Thread(new HoldLockThread(a,b), "ThreadA").start();
// 线程2持有b锁,想要获取a锁,此时会产生死锁问题
new Thread(new HoldLockThread(b,a), "ThreadB").start();
}
}
判断死锁
jps -l: 查看当前运行的Java进程,获取想要得到的进程号;
jstack pid:查看当前进程的情况。
产生死锁的四个必要条件
1. 互斥条件
进程对所分配到的资源进行排它性使用。
2. 请求和保持条件
进程已经保持至少一个资源,又提出了新的资源请求,并且该资源已经被其它进程占有了。
3. 不剥夺条件
进程已获得的资源,未使用完之前不能被剥夺。
4. 环路等待条件
发生死锁时,必然存在一个资源请求环形链。(A等B,B等A)
死锁与数据库
原网址
数据库中有两种基本的锁类型:排它锁(X锁,不可读取与修改)与共享锁(S锁,可读取不可修改)。
常见情况与解决方案
事务之间对资源访问顺序的交替
- 原因: A访问表S1(锁住),企图访问S2,;B访问表S2(锁住),企图访问S1。
- 解决方案:
进行程序的逻辑调整(破坏环路等待条件)。
并发修改同一记录
- 原因:A查询一条记录,并准备进行修改(由共享锁上升到排它锁);此时B正准备对该记录进行修改(排它锁),然而排它锁需要等共享锁被释放才会进行修改操作,而A由于B持有排它锁而无法上升,因此也不可能释放共享锁,由此产生了死锁。
- 解决方案:
a. 乐观锁:基于版本记录机制实现:即为数据增加一个版本标识。更新加一,大于则更新。但是可能会造成脏数据(读取撤销数据)被更新到数据库中。
b. 悲观锁:依靠数据库的锁机制实现(串行)。对于高并发需求场景不适用。
c. 更新锁(sqlserver):兼容共享锁,但是同一时间段只有一把更新锁,并且只有更新锁能上升为排它锁。
索引不当导致全表扫描
- 原因:全表扫描会将行级锁上升为表级锁,如果出现多个这样的事务,则很容易产生死锁和阻塞。
- 解决方案:
SQL语句不要使用太复杂的关联多表查询,对于全表扫描的SQL语句,建议相应索引进行优化。
分布式锁
任何一个分布式系统都无法同时满足一致性、可用性和分区容错性,最多满足两项。
在分布式环境下,考虑的是多进程的情况,因此,需要将标记(锁的实质)存储在一个所有进程都能看到的地方。
定义:在分布式模型下,数据只有一份,此时需要利用锁的技术来控制某一时刻修改数据的进程数。考虑网络的延时与不可靠。
特点:
- 互斥性;(不同节点不同线程)
- 可重入性;(同一线程获取一次后还能继续获取)
- 锁超时;(解除不剥夺条件)
- 支持阻塞与非阻塞;
- 支持公平锁;
- 高效可用;
进程间通信方式
- 管道/匿名管道(缓冲区,单向数据流)
- 有名管道(以文件形式存在于内存,双向)
- 信号(进程产生,内核发送)
- 消息队列(存于内核,支持随机查询)
- 共享内存(最快,多个进程共享一块内存空间)
- 信号量(本质是一个计数器,用于进程间的同步/对资源的有序访问)
- 套接字(本质对TCP/IP的封装,方便主机之间的通信)
Linux操作
常用命令
pwd:显示当前目录
chmod:权限更改(4,2,1 / 当前用户,用户所属组,其它用户)
find [PATH][option][action]
top:动态查看当前运行进程
ps:查看某个时间点的运行进程
netstat:查看系统端口使用情况
df:列出文件系统整体磁盘使用量
du:评估文件系统的磁盘使用量
ln:连接(硬软连接的区别)
什么是安装Linux所需的最小分区数量,如何查看系统启动信息?
单独一个 /root 分区足以执行所有的系统任务,但是建议至少三个分区 /root,/boot,/swap。
启动信息的检查,使用 dmesg
补充:常用分区作用
- /boot:内核启动文件
- /home:用户目录
- /usr:存放软件的位置
- /root:系统管理员目录
- /swap:交换分区(虚拟内存,内存不足时,将部分磁盘空间当成内存)
Linux机器上跟踪系统事件的守护进程名?
syslogd 命令,负责跟踪系统信息,并将日志存储于特定文件。