The Magnificent JavaJava学习笔记

多线程基础(四)之死锁

2017-03-09  本文已影响25人  承香墨影

版权声明:

本账号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影所有。

允许有条件转载,转载请附带底部二维码。

一、前言

在Java中,如果使用到多线程的技术,除了要考虑同步锁之外,还需要考虑,在使用锁的过程中,可不可能造成死锁的情况。本篇就死锁的情况进行一个简单的讲解,让大家在使用的过程中,了然于胸。

二、什么是死锁?

先看看百度百科的解释:

所谓死锁:是指两个或两个以上的进程在执行过程中,由于竞争资源或由彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。彼此称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

在Java线程的实现中,死锁是一个非常经典和常见的问题,当业务复杂度低的时候,一般都是可以避免的,但是一旦业务复杂度增大,就可能导致多个线程在执行的过程中,等待了根本不可能被释放的锁,从而导致后面所有的任务都被挂起无法得到执行。这样的情况下,程序将无法继续执行,会出现线程“假死”的情况。

三、为什么会出现死锁

死锁其实就是一种Bug,在程序设计的时候,只要避免在双方互相持有对方的锁资源的情况,就是不要有互相等待的情况。一般而言就不会出现死锁。

举个例子:

小明说,如果小新买了梨,那我也买点苹果。

小新说,如果小明买苹果了,那我就买点梨。

结果可想而知,当自己的业务需要受到对方影响的情况下,如果这种影响说是相互互斥而不存在例外情况的话,就会出现死锁,这个例子中,小明和小新永远都不会去买自己需要的水果。

那么死锁可不可怕,其实说严重也严重,但是一般而言,因为太严重了,通常出现死锁之后,业务无法继续下去,是可以被开发人员感知到的,而得到处理。

四、出现死锁如何解决?

出现死锁的情况下,只需要我们dump线程来查看到底是哪个些线程出现了死锁的情况。

其实JDK自带了命令行工具来帮助我们dump出线程的堆栈。

  1. 首先使用jps,找到线程的PID。
  1. 再通过jstack获取制定PIC的ThreadDump。

它们的使用方式非常的简单:

主要是找关键字:“java.lang.Thread.State:BLOCKED”,如果多个线程出现了的状态都是BLOCKED,那么可能就是造成死锁的原因。

五、立几个消灭死锁的军规

既然死锁是非常严重的Bug,会造成多线程互相等待,从而影响业务。那么我们立几条消灭死锁的军规,在开发中严格准照,一般就可以避免大多数可能被死锁的情况。

  1. 避免一个线程同时获取多个锁。单一职责思路,一个线程只干一件事情。
  1. 避免一个线程在锁内同时占用多个资源。单一职责也是相互的。
  1. 尝试使用lock.tryLock(timeout)来替代使用的同步锁。这种定时锁会有超时机制,保证了在出现可能死锁的情况下,依然有例外情况下可以跳出控制。
  1. 对于数据库锁,加锁和解锁必须在一个数据库连接中,否则会出现解锁失败的情况。这个不难理解,不是同一个数据库连接,解锁的就已经不是之前加锁的锁了。
公众号二维码.jpg
上一篇 下一篇

猜你喜欢

热点阅读