以下是一些自己的理解,如果有不对的地方还请大神指点。
关于死锁再多线程和数据库访问中都有存在,而死锁之所以会产生,情景其实是相似的。
为什么会有锁
当两个进程同时去修改一个数的时候,特别是做那种累加的操作时,例如,total=10:
A操作:total(10) + 10 =》20
B操作:total(20) + 30 =》50
但是如果A先获取total=10,在没有进行累加操作的时候,B就获取了total,那么此时total=10,结果就会变成:
A操作:total(10) + 10 =》20
B操作:total(10) + 30 =》40
由于B在读取后,数据被A操作,是的B读取到的值已经过时,而B的操作实际上是对过时数据操作,并且覆盖了中间A操作。这种像total的数据,应保持数据的一致性,读取和操作时,数据的实际值应该当时相同的。因此就需要加锁。对应到C#种,就有线程锁local这种操作。数据库中就有共享锁,排他锁的存在。
产生的四个必要条件及理解:
- 互斥条件。一个资源这能被一个进程占用。
- 请求和保持条件。占有了一个资源,还可以去请求它资源,如果其他资源被占用就会保持占有,并等待请求的资源释放。
- 不可剥夺条件。资源一旦被占有,就不能被其他进程抢走,除非自己释放掉
- 循环等待条件。进程行程一个环,而每一个进程都在请求并等待相邻进程释放资源。
出现死锁的几个情况
1 . 多表访问顺序不同(共享锁和排它锁时互斥的)
A操作修改A表(排它锁),B操作查询B表(共享锁)
A操作修改B表(排它锁)=》 B表被B占有 =》A操作等待
B操作修改A表(排它锁)=》 A表被A占有 =》B操作等待
=》AB互相等待 =》死锁
A操作插叙B表(共享锁)=》 共享锁不互斥 =》A操作完成
B操作修改A表(排它锁)=》 A操作已经释放A =》B操作完成
所以以上的例子,对于同一个表都是读,那么即使顺序不同也没有关系,但是存在了对两个表的读操作,并且不是在一个操作中,并且出现顺序不同就会造成死锁了。