Java、数据库、OS死锁小结

死锁最简单的场景就是,A拿着a资源,必须等拿到b资源后才释放a资源;B拿着b资源,必须等拿到a资源后才释放b资源。

 

所以死锁的性质

一、独占(像synchornized和ReentrantLock一样)

1.同时只能一个人用

2.后面的人只能排队

3.不可把使用者赶出去

二、成环

 

Java产生死锁的根本原因也是如此:在获取一个锁的同时,又去申请另外的锁

 

谈论数据库前,先讲一些数据库基础知识

数据库的4种异常现象及隔离级别

1.脏读。正常情况下会以为这样的操作是脏读——事务1先读了A行,事务2然后改了,所以拿到了一个脏数据。

当然不是这样理解的。这是对事务没有理解到位,事务是一个时间段性质的东西,比如在这个事务的时间段内修改了数据库,虽然你没有提交,但是对数据库的改变确实是真实发生的。但是由于你的事务还未提交,你的事务随时有回滚的可能,事务记录了你的操作,如果你回滚了,那么数据库就会被恢复到之前的样子。

所以我们可以知道,如果你修改了数据库的东西,但是你这个事务又没有提交。如果这个时候有人读了,就很危险了,因为你是有可能会回滚这个事务的,一旦你回滚了这个事务,那就是脏读了。

2.怎么解决呢?我们规定,在写的事务未提交之前,我们不能读。

可是这样还是有安全隐患,假如我们一个事务,先读了一次,然后另一个事务过来修改了一个值,我们原来的事务再次读了一次,惊讶地发现上次读的值和这一次读的值不一样了。

3.怎么解决呢?我们规定,在读的事务未提交之前,我们不能写,但是可以读。

可是还是有问题,比如一个事务改了所有行,但是另一个事务增加了一行,这个时候第一个事务就很奇怪,不是都改过了吗?

4.怎么解决呢?我修改一张表,就要锁住一张表。

 

 

数据库的死锁

情景1:

事务1想查询A行,修改B行

事务2想查询B行,修改A行

同时执行了前半句话,这个时候B行被事务1加了共享锁,A行被事务2加了共享锁,mysql的默认数据库隔离级别——读的事务没有提交前,我们可以读,但是不能写。这个级别下,共享锁是不能升级为独占锁的,因为读的事务没有提交前是不可以写的。所以事务1想修改B,事务2想修改A是做不到的。

解决:这是逻辑问题,需要调整逻辑

 

情景2:

double click

一个事务是先读取A行,再修改A行。这个时候如果应用层误点击两次,发起了两个这样的事务,这样两个事务就都读取了A,但是修改就做不了了,原理和上面有一点小出入,上面说了共享锁不能升级为独占锁,那是针对不同事务而言的。其实同一个事务的共享锁是可以升级成独占锁的(前提是没有另外的共享事务存在)。但是这里有两个事务,所以就不能升级了。

解决:乐观锁

    原文作者:java锁
    原文地址: https://blog.csdn.net/qq_36523667/article/details/81189123
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞