Java死锁问题学习笔记

Java死锁问题学习笔记

设计一个案例:
多线程运行环境下,假设程序要访问一个共享变量,对共享变量计算的中间结果用打印机打印出来,而打印机一次只允许一个线程访问

分析:
显然,一个线程要获取共享变量的访问权(对被用来同步访问的共享变量那把锁加锁——lockA),此外还要获取对打印机的访问权(对被用来同步访问打印机的锁成功加锁——lockB)。

public class Demo1 {
     static Object lockA = new Object();
     static Object lockB = new Object();

    public static void main(String[] args) {

        ABThread abThread = new ABThread();
        BAThread baThread = new BAThread();

        abThread.start();
        baThread.start();
    }


}

// 向访问共享变量,在访问打印机,将对共享变量计算的结果发送到打印机
class ABThread extends Thread {

    @Override
    public void run() {
        // 首先,尝试访问共享变量
        synchronized (Demo1.lockA) {
            try {
                Thread.sleep(2000);
                System.out.println("ABThread 加 lockA锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 访问共享变量做计算,得到一些结果
            synchronized (Demo1.lockB) {
                // 把共享变量计算的结果发送到打印机来打印
                System.out.println("ABThread 加 lockB锁");
            }

        }

    }
}

// 先获取打印机的访问权,在尝试访问共享变量,将共享变量计算结果发送到打印机打印
class BAThread extends Thread {

    @Override
    public void run() {
        // 首先,尝试访问打印机
        synchronized (Demo1.lockB) {
            // 获取打印机的访问权
            try {
                Thread.sleep(2000);
                System.out.println("BAThread 加 lockB锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            synchronized (Demo1.lockA) {
                //访问共享变量, 计算出结果,把结果发送到打印机打印
                System.out.println("BAThread 加 lockA锁");
            }
        }
    }
}

运行结果:
在这里插入图片描述
可以看出程序没有运行结束(发生了死锁现象)

死锁的问题:
死锁是指两个以上的线程在执行过程中,因为争夺资源而产生的一种相互等待的现象。

死锁问题的两种常见解决方式:
1.将多线程获取锁的顺序调整相同
2.再定义一把新的锁,利用这把锁(synchronized+该对象),实现将加多把锁的操作变成一个原子操作

(原子操作即一组不可分割的操作,要么全做,要么一点也不做)

解决方案一的代码实现:

public class Demo1 {
    static Object lockA = new Object();
    static Object lockB = new Object();

    public static void main(String[] args) {

        ABThread abThread = new ABThread();
        BAThread baThread = new BAThread();

        abThread.start();
        baThread.start();
    }


}

// 向访问共享变量,在访问打印机,将对共享变量计算的结果发送到打印机
class ABThread extends Thread {

    @Override
    public void run() {
        // 首先,尝试访问共享变量
        synchronized (Demo1.lockA) {
            try {
                Thread.sleep(2000);
                System.out.println("ABThread 加 lockA锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 访问共享变量做计算,得到一些结果
            synchronized (Demo1.lockB) {
                // 把共享变量计算的结果发送到打印机来打印
                System.out.println("ABThread 加 lockB锁");
            }

        }

    }
}

// 先获取打印机的访问权,在尝试访问共享变量,将共享变量计算结果发送到打印机打印
class BAThread extends Thread {

    @Override
    public void run() {
        // 首先,尝试访问打印机
        synchronized (Demo1.lockA) {
            // 获取打印机的访问权
            try {
                Thread.sleep(2000);
                System.out.println("BAThread 加 lockB锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            synchronized (Demo1.lockB) {
                //访问共享变量, 计算出结果,把结果发送到打印机打印
                System.out.println("BAThread 加 lockA锁");
            }
        }
    }
}

运行结果:
在这里插入图片描述
解决方案二的代码实现:

public class Demo1 {
    static Object lockA = new Object();
    static Object lockB = new Object();
    static Object allLock=new Object();

    public static void main(String[] args) {

        ABThread abThread = new ABThread();
        BAThread baThread = new BAThread();

        abThread.start();
        baThread.start();
    }


}

// 向访问共享变量,在访问打印机,将对共享变量计算的结果发送到打印机
class ABThread extends Thread {

    @Override
    public void run() {
        synchronized(Demo1.allLock){
            // 首先,尝试访问共享变量
            synchronized (Demo1.lockA) {
                try {
                    Thread.sleep(100);
                    System.out.println("ABThread 加 lockA锁");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 访问共享变量做计算,得到一些结果
                synchronized (Demo1.lockB) {
                    // 把共享变量计算的结果发送到打印机来打印
                    System.out.println("ABThread 加 lockB锁");
                }
            }
        }
    }


}

// 先获取打印机的访问权,在尝试访问共享变量,将共享变量计算结果发送到打印机打印
class BAThread extends Thread {

    public void run() {
        synchronized (Demo1.allLock) {
            // 首先,尝试访问打印机
            synchronized (Demo1.lockB) {
                // 获取打印机的访问权
                try {
                    Thread.sleep(2000);
                    System.out.println("BAThread 加 lockB锁");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (Demo1.lockA) {
                    //访问共享变量, 计算出结果,把结果发送到打印机打印
                    System.out.println("BAThread 加 lockA锁");
                }
            }
        }
    }
}

运行结果截图:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值