最近有学习java软件开发的朋友,在去面试java相关岗位的时候据说经常会被问到有关java中死锁的问题。那么想请问感兴趣的朋友们,你们知道如何避免死锁吗?知道在什么情况下会导致死锁的情况发生吗?
其实并发程序一旦死锁,一般我们只能重新启动应用。解决死锁问题最好的办法就是避免死锁。
下面我们一起来看看死锁发生的条件有哪些吧。
首先是互斥,因为共享资源是只能被一个线程占用的;
其次是占有且等待,例如线程 t1 已经取得共享资源 s1,那么在尝试获取共享资源 s2 的时候,不不会释放共享资源 s1的;
还有不可抢占的问题,因为其他线程是不能强行抢占线程 t1 占有的资源 s1的;
最后可能就是循环等待的问题了,比如说线程 t1 等待线程 t2 占有的资源,线程 t2 等待线程 t1 占有的资源
看完以上情况下会发生死锁的问题,下面还是得了解一下避免死锁的方法呢,
我们可以这样看,对于以上 4 个产生死锁的条件,如果说破坏了其中一个条件,那么其实就可以避免死锁的发生了。下面我们一起分析一下:
第一个条件 "互斥" ,是不能被破坏的,因为加锁的目的就是为了保证互斥。
剩下的其他三个条件,我们可以尝试。
首先是一次性申请所有的资源,破坏 "占有且等待" 条件。占有部分资源的线程进一步申请其他资源时,如果申请不到的话,可以主动释放它已经占有的资源,破坏 "不可抢占" 的条件。
其次是破坏 "循环等待" 条件,按序申请资源就可以做到了其实。
最后是使用管理类一次性申请所有的资源,可以破坏 "占有且等待" 条件。示例如下:
package constxiong.concurrency.a023; import java.util.HashSet; import java.util.Set; /** * 测试 一次性申请所有的资源,破坏 "占有且等待" 条件示例 * @author ConstXiong * @date 2019-09-24 14:04:12 */ public class TestBreakLockAndWait { //单例的资源管理类 private final static Manger manager = new Manger(); //资源1 private static Object res1 = new Object(); //资源2 private static Object res2 = new Object(); public static void main(String[] args) { new Thread(() - > { boolean applySuccess = false; while (!applySuccess) { //向管理类,申请res1和res2,申请失败,重试 applySuccess = manager.applyResources(res1, res2); if (applySuccess) { try { System.out.println("线程:" + Thread.currentThread() .getName() + " 申请 res1、res2 资源成功"); synchronized(res1) { System.out.println("线程:" + Thread.currentThread() .getName() + " 获取到 res1 资源的锁"); //休眠 1秒 try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } synchronized(res2) { System.out.println("线程:" + Thread.currentThread() .getName() + " 获取到 res2 资源的锁"); } } } finally { manager.returnResources(res1, res2); //归还资源 } } else { System.out.println("线程:" + Thread.currentThread() .getName() + " 申请 res1、res2 资源失败"); //申请失败休眠 200 毫秒后重试 try { Thread.sleep(200); } catch (Exception e) { e.printStackTrace(); } } } }) .start(); new Thread(() - > { boolean applySuccess = false; while (!applySuccess) { //向管理类,申请res1和res2,申请失败,重试 applySuccess = manager.applyResources(res1, res2); if (applySuccess) { try { 无锡妇科医院哪家好 http: //www.xasgfk.cn/ System.out.println("线程:" + Thread.currentThread() .getName() + " 申请 res1、res2 资源成功"); synchronized(res2) { System.out.println("线程:" + Thread.currentThread() .getName() + " 获取到 res1 资源的锁"); //休眠 1秒 try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } synchronized(res1) { System.out.println("线程:" + Thread.currentThread() .getName() + " 获取到 res2 资源的锁"); } } } finally { manager.returnResources(res1, res2); //归还资源 } } else { System.out.println("线程:" + Thread.currentThread() .getName() + " 申请 res1、res2 资源失败"); //申请失败休眠 200 毫秒后重试 try { Thread.sleep(200); } catch (Exception e) { e.printStackTrace(); } } } }) .start(); } }
那么以上就是有关java死锁问所有内容了,如果你还想了解更多java一些知识问答,记得关注本站消息哦。