死锁的例子演示_第1页
死锁的例子演示_第2页
死锁的例子演示_第3页
死锁的例子演示_第4页
死锁的例子演示_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、死锁的例演 ?死锁定发在并发场景中。我们为了保证线程安全,有时会给程序使各种能保证并发安全的具,尤其是锁,但是如果在使过程中处理不得当,就有可能会导致发死锁的情况互不相让死锁是种状态,当两个(或多个)线程(或进程)相互持有对所需要的资源,却都不主动释放中所持有的资源,导致家都获取不到想要的资源,所有相关的线程(或进程)都法继续往下执,在未改变这种状态之前都不能向前推进,我们就把这种状态称为死锁状态,认为它们发了死锁。通俗的讲,死锁就是两个或多个线程(或进程)被限期地阻塞,相互等待对中资源的种状态两个线程的例此时我们有两个线程,分别是线程 A 和线程 B,假设线程 A 现在持有了锁 A,线程 B

2、 持有了锁 B,然后线程 A 尝试去获取锁 B,当然它获取不到,因为线程 B 还没有释放锁 B。然后线程 B 来尝试获取锁 A,同样线程 B 也获取不到锁 A,因为锁 A 已经被线程 A 持有了。这样来,线程 A 和线程 B 就发了死锁,因为它们都相互持有对想要的资源,却不释放中的资源,形成相互等待,且会直等待下去多个线程造成死锁的情况死锁不仅仅存在于两个线程的场景,在多个线程中也同样存在。如果多个线程之间的依赖关系是环形,存在环路的依赖关系,那么也可能会发死锁,如下图所我们看到在这个例中,先线程 1 持有了锁 A,然后线程 2 持有了锁 B,然后线程 3 持有了锁 C,现在每个线程都分别持有

3、把锁。接下来线程 1 想要去持有锁 B,可是它获取不到,因为现在锁 B 正在线程 2 的;接下来线程 2 去尝试获取锁 C, 它同样也获取不到,因为现在锁 C 在线程 3 的;然后线程 3 去尝试获取锁 A ,当然它也获取不到,因为锁 A 现在在线程 1 的,这样来线程1、线程 2 和线程 3 相互之间就形成了个环,这就是在多线程中发死锁的情况。所以不仅是两个线程,多个线程同样也有可能会发死锁的情况死锁的影响死锁的影响在不同系统中是不样的,影响的部分取决于当前这个系统或者环境对死锁的处理能数据库中例如,在数据库系统软件的设计中,考虑了监测死锁以及从死锁中恢复的情况。在执个事务的时候可能需要获取

4、多把锁,并直持有这些锁直到事务完成。在某个事务中持有的锁可能在其他事务中也需要,因此在两个事务之间有可能发死锁的情况,旦发了死锁,如果没有外部涉,那么两个事务就会永远的等待下去。但数据库系统不会放任这种情况发,当数据库检测到这组事务发了死锁时,根据策略的不同,可能会选择放弃某个事务,被放弃的事务就会释放掉它所持有的锁,从使其他的事务继续顺利进。此时程序可以重新执被强终的事务,这个事务现在就可以顺利执了,因为所有跟它竞争资源的事务都已经在刚才执完毕,并且释放资源了JVM 中在 JVM 中,对于死锁的处理能就不如数据库那么强了。如果在 JVM 中发了死锁,JVM 并不会动进处理,所以旦死锁发,就会

5、陷穷的等待率不但危害死锁的问题和其他的并发安全问题样,是概率性的,也就是说,即使存在发死锁的可能性,也并不是 100% 会发的。如果每个锁的持有时间很短,那么发冲突的概率就很低,所以死锁发的概率也很低。但是在线上系统,可能每天有千万次的“获取锁”、“释放锁”操作,在量的次数前,整个系统发问题的率就会被放,只要有某次操作是有风险的,就可能会导致死锁的发也正是因为死锁“不定会发”的特点,导致提前找出死锁成为了个难题。压测试虽然可以检测出部分可能发死锁的情况,但是并不以完全模拟真实、长期运的场景,因此没有办法把所有潜在可能发死锁的代码都找出来旦发了死锁,根据发死锁的线程的职责不同,就可能会造成系统崩

6、溃、性能降低甚整个系统崩溃等各种不良后果。且死锁往往发在并发、负载的情况下,因为可能会直接影响到很多户,造成系列的问题。以上就是死锁发率不但是危害的特点发死锁的例/*/System.out.println(+Thread.currentThread().getName() + flag + flag);Thread.sleep(500);System.out.println( 1);synchronized (o2) try Thread.sleep(500); catch (Exception e) e.printStackTrace();synchronized (o1) System.o

7、ut.println( 2);public static void main(String argv) MustDeadLock r1 = new MustDeadLock();MustDeadLock r2 = new MustDeadLock();r1.flag = 1;r2.flag = 2;Thread t1 = new Thread(r1, t1);Thread t2 = new Thread(r2, t2);t1.start();t2.start();可以看到,在这段代码中有个 int 类型的 flag,它是个标记位,然后我们新建了 o1 和 o2、作为 synchronized

8、的锁对象在 run 法,它会先打印出当前线程的名字,然后打印出当前线程 flag 的值是多少如果 flag 等于 1,就会先获取 o1 这把锁,然后休眠 500 毫秒,再去尝试获取 o2 这把锁并且打印出线程1获得了两把锁如果 flag 等于 2,那么情况恰恰相反,线程会先获取 o2 这把锁,然后休眠 500 毫秒,再去获取 o1 这把锁,并且打印出线程2获得了两把锁在 main 法中新建了两个本类的实例,也就是两个 Runnable 对象,并且把它们的 flag 分别改为 1 和 2:r1 的 flag 设置为 1,r2 的flag 设置为 2。然后新建两个线程,分别去执这两个 Runnab

9、le 对象,执 r1 和 r2 这两个线程的名字分别叫做 t1 和 t2,最后我们把两个线程给启动起来程序的种执结果t1flag1t2flag2这的重点就在于程序执到此时还在继续执,并没停,并且它永远不会打印出“线程 1 获得了两把锁”或“线程 2 获得了两把锁”这样的语句,此时这就发了死锁对发死锁这个过程进分析当第 1 个线程运的时候,它会发现的 flag 是 1 ,所以它会尝试先获得 o1 这把锁,然后休眠 500 毫秒在线程 1 启动并休眠的期间,线程 2 同样会启动起来。由于线程 2 的 flag 是 2,所以它会进到下 的 if (flag = 2) 对应的代码块中,然后线程 2 先会去获取 o2 这把锁。也就是说在线程 1 启动并获取到 o1 这把锁之后进休眠的期间,线程 2 获取到了 o2这把锁,然后线程 2 也开始 500 毫秒的休眠。当线程 1 的 500 毫秒休眠时间结束后,它将尝试去获取 o2 这把锁,此时 o2 这个锁正被线程 2 持有,所以线程 1 法获取到的 o2紧接着线程 2 也会苏醒过来,它将尝试获取 o

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论