Java学习笔记80. 关于死锁

死锁,本质上是一个哲学问题。

当一个线程先占有了同步类(synchronized)的资源A,同时接着要求同步类的资源B。而恰恰在这中间,另一个线程捷足先登,占有了同步类的资源B,同时接着要求资源A。而此时资源A已经被第一个线程占有了。于是,这两个线程的代码都执行不下去了,它们都在等对方释放资源,好继续往下执行,这时候,程序就形成了“死锁”的状态。

所谓同步类的资源,就是被synchronized关键字修饰的资源,一般是语句块。这种资源,是哪个线程先执行,哪个线程先独自占有,直到执行完所有的代码,才释放给其它的线程使用。

下面写一个死锁的例子程序:

/*假设一个人需要拿到两把钥匙才能完成一件任务。
* 第一个人先开始执行任务,拿到了keyOne,准备拿keyTwo的时候,第二个人也开始了任务,并抢先拿到了keyTwo。
* 这时候,第1个人需要拿到keyTwo才能完成任务,第2个人需要拿到keyOne才能完成任务。但是钥匙在对方手里,谁也玩不成任务
* 这样,问题就无解了,形成了僵局
*/
public class TestDeadLock extends Thread{    //线程类TestDeadLock
    static String keyOne="keyone";    //第一把钥匙
    static String keyTwo="keytwo";    //第二把钥匙

    static boolean flag = true;    //设置旗标,规定先进来的线程,先去拿第一把钥匙;后进来的线程,先去拿第2把钥匙
    public void run(){            //覆盖run方法
        if(flag){                //先进来的人先去运行keyOne
            flag = false;        //设置旗标,以维持运行规则
            synchronized(keyOne){    //拿第一把钥匙
                System.out.println("I have "+keyOne+". I need "+keyTwo);
                try{
                    Thread.sleep(100);    //让第一个线程睡100毫秒,好让第二个线程执行
                }catch(InterruptedException e){
                        e.printStackTrace();
                }
                synchronized(keyTwo){    //第一个线程睡完100毫秒之后,接着拿第二把钥匙,但是在它睡着的时候,第二把钥匙被第二个线程拿走了
                    System.out.println("I have "+keyTwo);
                }
            }
        }
        else        //后进来的线程,执行这一段
            {
            flag = true;        //设置旗标
            synchronized(keyTwo){    //去拿第二把钥匙
                System.out.println("I have "+keyTwo+". I need "+keyOne);
                try{
                    Thread.sleep(100);    //第二个线程也睡100毫秒,好让第一个线程继续执行
                }catch(InterruptedException e){
                        e.printStackTrace();
                }
                synchronized(keyOne){    //第二个线程睡晚100毫秒之后,接着去拿第一把钥匙,但是第1把钥匙早就被第一个线程拿走了,只能等待
                    System.out.println("I have "+keyTwo);
                }
            }
        }
    }
public static void main(String[] args){
    //分别启动两个线程
    new TestDeadLock().start();
    new TestDeadLock().start();
    
}
}

执行结果如下:

可以发现,两个线程分别执行到了一半,然后都在等待对方释放资源,对方释放了资源,才能继续玩下去。

如果要避免这种情况的发生,就要在设计思路上更改。比如两个线程要执行,必须先得到第一把钥匙,才能去拿第二把钥匙,这样在规则上避免了相互抢夺资源的状况。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值