多线程:死锁,乐观锁,悲观锁

死锁:

两个或者多个进程竞争统一资源而形成的僵持的局面,若无外力作用,将无法推进。

本质原因:

1)系统资源有限

2)进程推进顺序不合理

死锁的条件:

(1)互斥。某个资源在一段时间只能有一个进程占有,只有当使用该资源的进程释放后,其他进程才能占有该资源。

(2)请求和保持。进程A已经拥有了一些资源,现在要访问其他资源,A进程阻塞,但是在A等待的过程中,不会释放已有的资源,

(3)不剥夺。不可抢占条件,进程在未使用完资源之前,不能被其他进程抢占,只能由该进程的占有者自行释放。

(4)环路等待。存在一个等待序列{P1,P2,P3...Pn},其中,P1等待P2所占有的资源,P2等待P3所占有的某种资源,Pn等待P1占有的某种资源。

上述4个条件只要有1个不满足,死锁就会排除。

解决死锁的方法:

死锁的预防,避免,检测与恢复

预防:确保系统永远不会进入死锁状态。打破4个条件中的一个或者几个

避免:在使用前进行判断,只允许不会产生死锁的进程申请资源。安全序列,银行家算法,加锁顺序

检测与解除:检测到运行系统进入死锁,进行恢复。允许系统进入死锁状态。

乐观锁:

假设不会发生并发冲突。只在提交时是否违反数据完整性。不能解决脏读的问题。适用于并发量非常大的情况。

每次拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断在此期间别人有没有更新这个数据,可以使用版本号等机制。适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制。java.util.concurrent.atomic包下的原子变量类就是使用乐观锁的一种实现CAS实现的。

hibernate乐观锁的实现:

基于version,版本号

基于timestamp,时间戳

悲观锁:

假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。

每次去拿数据的时候都认为别人会修改,所以每次拿数据的时候都会上锁,这样别人想拿这个数据时就会阻塞直到它拿到锁。传统的关系型数据库就用到了很多这种锁机制,比如行锁,表锁,读锁,写锁等,都是在操作之前先上锁。java里面的synchronized关键字就是悲观锁。并发访问性不好。

并发量不大,不允许脏读的情况下使用悲观锁

猜你喜欢

转载自blog.csdn.net/weixin_38108266/article/details/82843527
今日推荐