分布式锁正确打开方式 程序怎样实现死锁?该如何分析死锁?
程序怎样实现死锁?该如何分析死锁?
所谓死锁:是指两个或两个以上的进程在执行过程中因为争夺资源而相互等待的现象。如果没有外力,他们就无法前进。此时,系统被称为处于死锁状态或系统有死锁。这些总是互相等待的进程称为死锁进程。由于资源的占用是互斥的,当一个进程申请资源时,如果没有外力的协助,相关进程永远无法分配到必要的资源,这就产生了一种特殊的死锁现象。
虽然在运行过程中可能会出现死锁,但必须满足一定的条件,死锁必须满足以下四个必要条件。
1)互斥情况:指一个进程独占使用分配的资源,即一段时间内一个资源只被一个进程占用。如果此时有其他进程请求资源,请求者只能等待,直到占用资源的进程用完释放。
2)请求和保持条件:指已经保持了至少一个资源的进程,但是提出了新的资源请求,并且这个资源已经被其他进程占用。此时,请求进程被阻塞,但是它仍然持有它已经获得的其他资源。
3)非剥夺条件:指进程获得的资源,在用完之前不能被剥夺,用完之后才能自行释放。
4)循环等待条件:发生死锁时,必须有一个进程——一个环形的资源链,即进程集{P0,P1,P2,..,Pn}正在等待P1占用的一个资源;P1正在等待被P2占领的资源,...,并且Pn正在等待已经被P0占用的资源。
系统发生死锁后,应及时检测并采取适当措施解除死锁。目前,处理死锁的方法可以归纳为以下四种
1)防止死锁
这是一种比较简单直观的提前预防方法。方法是设置一些限制来破坏死锁的四个必要条件中的一个或多个,从而防止死锁。死锁预防是一种易于实现的方法,已被广泛使用。然而,所施加的限制往往过于严格,这可能导致系统资源利用率和系统吞吐量的降低。
2)避免死锁
这种方法也是一种预防策略,但不需要事先采取各种限制性措施来破坏死锁的四个必要条件,而是在动态分配资源的过程中使用一些方法来防止系统进入不安全状态,从而避免死锁。
3)检测死锁
这种方法不需要事先采取任何限制措施,也不需要检查系统是否进入了不安全区。这种方法允许系统在操作过程中出现死锁。但是,通过系统设置的检测机制,可以及时检测到死锁的发生,并准确地确定与死锁相关的进程和资源,然后采取适当的措施从系统中清除已经发生的死锁。
4)消除僵局
这与检测死锁是兼容的。测度集。当在系统中检测到死锁时,进程必须从死锁状态中释放出来。常见的实现方法是取消或挂起一些进程,以便回收一些资源,然后将这些资源分配给已经处于阻塞状态的进程,使其做好继续运行的准备。死锁检测和消除措施可以使系统获得更好的资源利用率和吞吐量,但也是最难实现的。
悲观锁:假设将发生并发,所有可能违反数据完整性的操作都将被屏蔽。
乐观锁定:假设不会发生并发,我们只会在提交操作时检查是否违反了数据完整性。乐观锁定可以 解决不了肮脏阅读的问题。
悲观锁,顾名思义就是悲观。每次获取数据的时候都认为别人会修改,所以每次获取数据的时候都会加锁,这样别人就会屏蔽它,直到它得到锁。传统的关系数据库中使用了许多这样的锁机制,如行锁、表锁、读锁、写锁等。,操作前全部锁定。
乐观锁,顾名思义,就是乐观。每次去取数据,他都认为别人不会修改,所以他赢了 不要锁。但是在更新的时候,他会判断这段时间别人有没有更新过数据,他可以使用版本号等机制。乐观锁定适用于多读应用程序类型,可以提高吞吐量。例如,如果数据库提供类似write_condition的机制,它实际上提供了乐观锁定。
我的头条号有更多关于发行、网站、开发语言等视频。你可以看看。
如何保证同一资源被多个线程并发访问时的完整性?
对于这个问题,我们首先想到的是使用synchronized关键字,这是一个解决方案,比如:
公共同步void setStatus(布尔b) {}
但是synchronized不适合高并发数据,会导致程序特别慢,不适合集群,负载均衡后数据会有问题。
我们使用另一种解决方案,redis分布式锁。redis是单线程服务,高效的键/值结构,支持高可用的分布式集群,可以让多台机器上的多个进程互斥相同的数据。
让 让我们谈谈redis从创建到使用的过程:
1.使用maven下载redis所依赖的包,在pom.xml中进行配置:
ltdependencygt ltartifactidgt spring-boot-starter-data-redi SLT/artifactIdgt
2.熟悉r:在设置新值之前获取以前的值。
3、新增redis类写锁,解锁方法:
redis的自动注入
@自动连线
私有字符串模板
/***
*锁定
* @param密钥id
* @param value当前时间超时
* @return*/
命令对应的公共布尔锁(String Key,String Value) {//setnx。
//可以设置值返回true,但是可以 不要将该值设置为返回false。
if(redisTemplate.opsForValue()。setIfAbsent(key,value)) { return true }
//确保只有一个线程获得锁。
字符串current value redis template . ops for value()。获取(键)
//如果锁过期,则存储的锁小于当前时间。
如果(!(当前值)ampamp(当前值)lt ()) {
//获取最后一次锁定的时间
string old value redis template . opsforvalue()。getAndSet(键,值)
如果(!(old value)amp old value . equals(current value)){ return true } } return false }
/**
*解锁
*/public void unlock(字符串键,字符串值){
尝试{
字符串current value redis template . ops for value()。get(key) if(!(当前值)ampamp当前值. equals(值)){
值()的Redisttemplate.ops。getOperations()。delete(key)} Catch(Exception e){([Redis分布式锁]解锁异常,{}
版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。