Java多线程——深入了解“死锁”

Java多线程——深入了解“死锁”

  在了解“死锁”前,对“死锁”的知识进行简单的梳理,“死锁”知识无非就是:什么“死锁”?“死锁”怎样产生?死锁的影响?如何避免“死锁”?这四大问题。

  众人皆知的“死锁”到底是什么?

  1、“死锁”是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些线程都将无法向前推进的状态。

  “死锁”到底是怎样产生的?

  2、死锁的产生原因:对并发资源的加锁成“环”。
   ①互斥:共享资源在某一时刻只能被一个线程占用。
   ②占有且等待:某线程拿到一个共享资源X占用后,还等待着被别的线程占用了的共享资源Y(该线程已经占有X,即要等待Y,还不释放X)。
   ③不可抢占:线程Thread1拿到对象锁x后,其他线程无法强行抢占x锁(需要等待Thread1执行完)。
   ④循环等待:线程T1拿到了资源X的锁后,去申请Y的锁;
         线程T2拿到了资源Y的锁后,去申请X的锁。

  “死锁”对程序有什么影响?

  3、在多线程中,“死锁”会造成线程的“假死”,严重影响程序的效率。

  举个栗子,展示会出现“死锁”的情况

		package com.xiaoaxiao.test.thread_test.book_test;
		
		/**
		 * Created by xiaoaxiao on 2019/7/17
		 * Description: 死锁
		 */
		
		class DealThread implements Runnable{
		
		    public String username;
		    public Object lock1 = new Object();
		    public Object lock2 = new Object();
		
		    public void setFlag(String username){
		        this.username = username;
		    }
		
		    @Override
		    public void run() {
		        if (username.equals("a")){
		            synchronized (lock1){
		                try {
		                    System.out.println("username = "+username);
		                    Thread.sleep(3000);
		                } catch (InterruptedException e) {
		                    e.printStackTrace();
		                }
		                synchronized (lock2){
		                    System.out.println(" 按lock1->lock2 代码顺序执行");
		                }
		            }
		        }
		        if (username.equals("b")){
		            synchronized (lock2){
		                try {
		                    System.out.println("username = "+username);
		                    Thread.sleep(3000);
		                } catch (InterruptedException e) {
		                    e.printStackTrace();
		                }
		                synchronized (lock1){
		                    System.out.println(" 按lock2->lock1 代码顺序执行");
		                }
		            }
		        }
		    }
		
		
		}
		
		public class DealThreadTest {
		
		    public static void main(String[] args) {
		
		        try {
		            DealThread t1 = new DealThread();
		            t1.setFlag("a");
		            Thread thread1 = new Thread(t1);
		            thread1.start();
		            Thread.sleep(1000);
		            t1.setFlag("b");
		            Thread thread2 = new Thread(t1);
		            thread2.start();
		        } catch (InterruptedException e) {
		            e.printStackTrace();
		        }
		    }
		}

  既然“死锁”对程序不好的影响如此之大,那应该如何避免“死锁”呢?

  4、避免“死锁”:
   ① 线程按照一定顺序加锁,避免嵌套加锁,只锁需要的部分,合理设计锁机制。
   ② 等待时间设置上限,设置获取锁时加锁的时限,若一个线程没有在给定的时限内成功获取所需要的锁,则会进行回退并释放该线程所有已经获得的锁。(Synchronized不具有该功能<死等>,Lock锁才有超时锁的概念)
   ③ 死锁检测(jstack)
   ④“银行家”算法
  详情可参考:Java多线程——死锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值