java学习——线程死锁+释放锁

目录

1.线程死锁

1.基本介绍

2.应用案例

2.释放锁

1.以下情况会释放锁:

2.以下操作不会释放锁:


1.线程死锁

1.基本介绍

多个线程占用了对方放入锁资源,但不肯相让,导致了死锁,在编程里面是一定要避免死锁的发生。

2.应用案例

public class DeadLock_ {
    public static void main(String[] args) {
            //模拟死锁现象
        DeadLockDemo deadLockDemo=new DeadLockDemo(true);
        DeadLockDemo deadLockDemo1 = new DeadLockDemo(false);
        deadLockDemo1.start();
        deadLockDemo.start();

    }
}
class DeadLockDemo extends Thread{
    static Object o1=new Object();
    static Object o2=new Object();
    boolean flag;
    public DeadLockDemo(boolean flag){
        this.flag=flag;
    }

    @Override
    public void run() {
        //如果flag为true,线程就会现持有o1对象锁,然后尝试去获取o2对象锁
        //如果线程a得不到o2的对象锁,就会Blocked
        //如果flag为False
        //如果线程b得不到o1的对象锁,就会Blocked
        if(flag){
            synchronized (o1) {

                System.out.println(Thread.currentThread().getName() + "进入1");
                synchronized (o2) {
                    System.out.println(Thread.currentThread().getName()+"进入2");
                }
            }
        }
        else{
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName()+"进入3");
                synchronized (o1){
                    System.out.println(Thread.currentThread().getName()+"进入4");
                }
            }
        }
    }
}

这里我们还是一样,继承Thread实现线程。在run方法里面我们实现了模拟死锁的代码。我们用if-else语句在其中添加了两个嵌套互斥锁模块。分别是:

 synchronized (o1) {

                System.out.println(Thread.currentThread().getName() + "进入1");
                synchronized (o2) {
                    System.out.println(Thread.currentThread().getName()+"进入2");
                }
            }
synchronized (o2) {
                System.out.println(Thread.currentThread().getName()+"进入3");
                synchronized (o1){
                    System.out.println(Thread.currentThread().getName()+"进入4");
                }
            }

在主函数开启Thread-0,Thread-1两个线程的时候,我们会发现他们分别同时获得了o1和o2两把锁,但要下一步的时候,我们发现无法执行下一步,因为Thread-0需要o2的锁,而Thread-1需要o1的锁。但他们都不肯放掉,所以他们就卡在这一步了。这种情况我们一般称为线程死锁。运行结果如下:

但如果代码如下:

public class DeadLock_ {
    public static void main(String[] args) {
            //模拟死锁现象
        DeadLockDemo deadLockDemo=new DeadLockDemo(true);
        DeadLockDemo deadLockDemo1 = new DeadLockDemo(false);
        deadLockDemo1.start();
        deadLockDemo.start();

    }
}
class DeadLockDemo extends Thread{
    static Object o1=new Object();
    static Object o2=new Object();
    boolean flag;
    public DeadLockDemo(boolean flag){
        this.flag=flag;
    }

    @Override
    public void run() {
        //如果flag为true,线程就会现持有o1对象锁,然后尝试去获取o2对象锁
        //如果线程a得不到o2的对象锁,就会Blocked
        //如果flag为False
        //如果线程b得不到o1的对象锁,就会Blocked
        if(flag){
            synchronized (o1) {

                System.out.println(Thread.currentThread().getName() + "进入1");

            }
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName()+"进入2");
            }
        }
        else{
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName()+"进入3");

            }
            synchronized (o1){
                System.out.println(Thread.currentThread().getName()+"进入4");
            }
        }
    }
}

结果如下: 

你会发现他并没有被锁上,因为在Thread-0需要o2的锁时,他o1的锁已经不需要了,也就放开了。Thread-1也是一样,所以他们并没有处于死锁的状态中。所以我们可以知道,在线程死锁的情况下,线程处于无锁可用的情况下。当然,死锁是一种很恐怖的情况,所以我们一般是避免这种情况。

2.释放锁

1.以下情况会释放锁:

  • 当前线程的同步方法,同步代码块执行结束。

  • 当前线程在同步代码块,同步方法中遇到break,return

  • 当前线程在同步代码块,同步方法中出现了未处理的Error或Exception,导致异常结束

  • 当前线程在同步代码块,同步方法中执行了线程对象的wait()方法,当线程暂停,并释放锁 

2.以下操作不会释放锁:

  •  线程在执行同步代码块或同步方法时,程序调用Thread.sleep(),Thread.yield()方法暂停当前线程的执行,不会释放锁。

  • 线程执行同步代码时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。ps:尽量避免使用suspend()和resume()来控制线程

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值