多线程09/线程死锁问题

柔情只为你懂 2023-10-04 16:39 172阅读 0赞

线程死锁问题

死锁

不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁

出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续

解决方法

  1. 专门的算法、原则
  2. 尽量减少同步资源的定义
  3. 尽量避免嵌套同步

首先写一个出现死锁的概率极低的代码

  1. package com.dxc;
  2. public class ThreadTest {
  3. public static void main(String[] args) {
  4. StringBuffer s1 = new StringBuffer();
  5. StringBuffer s2 = new StringBuffer();
  6. //该结构内有两把锁s1,s2
  7. new Thread(){
  8. public void run(){
  9. //第一把锁
  10. synchronized (s1){
  11. s1.append("a");
  12. s2.append("1");
  13. //第二把锁
  14. synchronized (s2){
  15. s1.append("b");
  16. s2.append("2");
  17. System.out.println(s1);
  18. System.out.println(s2);
  19. }
  20. }
  21. }
  22. }.start();
  23. //该结构内有两把锁s1,s2
  24. new Thread(new Runnable() {
  25. @Override
  26. public void run() {
  27. //第一把锁(与上面线程顺序错开)
  28. synchronized (s2){
  29. s1.append("c");
  30. s2.append("3");
  31. //第二把锁
  32. synchronized (s1){
  33. s1.append("d");
  34. s2.append("4");
  35. System.out.println(s1);
  36. System.out.println(s2);
  37. }
  38. }
  39. }
  40. }).start();
  41. }
  42. }

本次运行结果成功,无死锁

在这里插入图片描述

下面增加sleep语句,提高出现死锁的概率

  1. package com.dxc;
  2. public class ThreadTest {
  3. public static void main(String[] args) {
  4. StringBuffer s1 = new StringBuffer();
  5. StringBuffer s2 = new StringBuffer();
  6. //该结构内有两把锁s1,s2
  7. new Thread(){
  8. public void run(){
  9. //第一把锁
  10. synchronized (s1){
  11. s1.append("a");
  12. s2.append("1");
  13. //增加死锁概率
  14. try {
  15. Thread.sleep(100);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. //第二把锁
  20. synchronized (s2){
  21. s1.append("b");
  22. s2.append("2");
  23. System.out.println(s1);
  24. System.out.println(s2);
  25. }
  26. }
  27. }
  28. }.start();
  29. //该结构内有两把锁s1,s2
  30. new Thread(new Runnable() {
  31. @Override
  32. public void run() {
  33. synchronized (s2){
  34. s1.append("c");
  35. s2.append("3");
  36. //增加死锁概率
  37. try {
  38. Thread.sleep(100);
  39. } catch (InterruptedException e) {
  40. e.printStackTrace();
  41. }
  42. synchronized (s1){
  43. s1.append("d");
  44. s2.append("4");
  45. System.out.println(s1);
  46. System.out.println(s2);
  47. }
  48. }
  49. }
  50. }).start();
  51. }
  52. }

本次运行结果阻塞

因为上面线程拿到s1锁之后进行sleep,这时候系统时间片切换去执行下面的线程,下面的线程拿到s2锁后进行sleep,导致s1,s2两个锁都被占用,两个线程都无法进行下面的操作,出现死锁

在这里插入图片描述

死锁的理解:
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁

说明:

  1. 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续
  2. 我们使用同步时,要避免出现死锁。

死锁的练习题,直接看11:50


发表评论

表情:
评论列表 (有 0 条评论,172人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线09/线问题

    线程死锁问题 > 死锁 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁 出现死锁后,不会出现异常,不会出现提示,只

    相关 线

    死锁: 如果一个资源被一个线程占用,而且无法释放线程资源,导致其他线程无法访问这个字段,一直处于等待状态,这样就会形成 线程死锁。 例子: package com.

    相关 线

    / 死锁:二个线程同时锁住一个变量时。 锁住一个变量之后,尽快操作完成解锁,解锁之前不要再锁住其它变量,否则会互锁(死锁)。 /

    相关 线

    峨眉山月半轮秋,影入平羌江水流 Java线程的死锁一直都是经典的多线程问题;因为不同的线程都在等待根本不可能被释放的锁,从而导致所有的任务都不能继续执行; 示例代码:

    相关 线

    同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉。