Java多线程05—什么是线程的死锁?

简介: Java多线程05—什么是线程的死锁?

线程的死锁问题

  1. 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
  2. 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续

Java多线程01—线程的初步理解和基于Thread类创建线程:练习题答案的方法二中提到了匿名子类启动多线程

死锁的演示一(细看):

package com.jsm.java3;
/*
演示线程的死锁问题
 */
public class ThreadTest {
    public static void main(String[] args) {
        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();
        //第一部分
        new Thread(){
            @Override
            public void run() {
                synchronized (s1){
                    s1.append("a");
                    s2.append("1");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");
                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();
        //第二部分
        new Thread(new Runnable() {//匿名对象
            @Override
            public void run() {
                synchronized (s2){
                    s1.append("c");
                    s2.append("3");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");
                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();
    }
}
  1. 首先要知道不加sleep的时候的运行结果是什么。

运行结果:

ab
12
abcd
1234

  1. 代码解释:第一部分运行起来,握住s1锁,然后sleep延迟100毫秒,这时候第二部分就运行握住s2,然后也开始sleep,当两部分都“醒了”的时候呢,都等着去拿对方的锁,就互相僵持,最好形成死锁,程序不会抛异常,也不会终止。我们在使用同步时,要避免死锁

死锁的演示二

package com.jsm.java3;
/*
死锁的演示
 */
class A {
   public synchronized void foo(B b) {
      System.out.println("当前线程名: " + Thread.currentThread().getName()
            + " 进入了A实例的foo方法"); // ①
      try {
         Thread.sleep(200);
      } catch (InterruptedException ex) {
         ex.printStackTrace();
      }
      System.out.println("当前线程名: " + Thread.currentThread().getName()
            + " 企图调用B实例的last方法"); // ③
      b.last();
   }

   public synchronized void last() {
      System.out.println("进入了A类的last方法内部");
   }
}

class B {
   public synchronized void bar(A a) {
      System.out.println("当前线程名: " + Thread.currentThread().getName()
            + " 进入了B实例的bar方法"); // ②
      try {
         Thread.sleep(200);
      } catch (InterruptedException ex) {
         ex.printStackTrace();
      }
      System.out.println("当前线程名: " + Thread.currentThread().getName()
            + " 企图调用A实例的last方法"); // ④
      a.last();
   }

   public synchronized void last() {
      System.out.println("进入了B类的last方法内部");
   }
}

public class DeadLock implements Runnable {
   A a = new A();
   B b = new B();

   public void init() {
      Thread.currentThread().setName("主线程");
      // 调用a对象的foo方法
      a.foo(b);
      System.out.println("进入了主线程之后");
   }

   public void run() {
      Thread.currentThread().setName("副线程");
      // 调用b对象的bar方法
      b.bar(a);
      System.out.println("进入了副线程之后");
   }

   public static void main(String[] args) {
      DeadLock dl = new DeadLock();
      new Thread(dl).start();
      dl.init();
   }
}
目录
相关文章
|
18天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
54 0
|
1月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
82 16
|
2月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
2月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
3月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
3月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
307 83
|
3月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
143 0
|
5月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
192 0
|
8月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
138 17