多线程加强(三)线程死锁的两种情况及解决办法

第一种情况: 多个线程共享同一资源,并且某一线程内又调度其他线程,让其他线程先运行。矛盾在于 A 线程 拿到资源锁运行中让线程B运行,线程B 运行需要资源锁。而锁在线程A 中,从而引起的互相等待。
线程A:

package cn.hncu.thread.deadLock.v1;

public class ThreadA implements Runnable{
    private S s = null;
    private Thread b=null;

    public ThreadA(S s, Thread b) {
        this.s = s;
        this.b = b;
    }

    @Override
    public void run() {
        System.out.println("ThreadA begin......");
        synchronized (s) {
            System.out.println("ThreadA拿到对象锁,进入同步块....");

            try {
                b.join();//拿着锁,调用线程B 引起了死锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadA, a="+s.a);
        }
    }

}

线程B

package cn.hncu.thread.deadLock.v1;

public class ThreadB implements Runnable{
    private S s = null;

    public ThreadB(S s) {
        super();
        this.s = s;
    }

    @Override
    public void run() {
        System.out.println("ThreadB begin......");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("ThreadB 睡后继续运行....");
        synchronized (s) {
           s.a = 100;
           System.out.println("ThreadB 已经完成对资源s.a的赋值,s.a="+s.a);
        }

    }
}

演示

package cn.hncu.thread.deadLock.v1;

public class Demo1 {
    public static void main(String[] args) {
        S s = new S();
        Thread b = new Thread( new ThreadB(s) );
        Thread a = new Thread( new ThreadA(s, b) );

        b.start();
        a.start();
    }
}

class S{
    public int a=0;
}

结果 线程一直运行(右边红色可以看出)
这里写图片描述
解决办法: 设计线程时,注意规范避免在一个线程内部调用其他的线程。

线程死锁的第二种情况:多个线程需要多个资源,可能会造成一个线程拿部分资源。从而造成互相等待的情况死锁。
解决办法: 把线程需要的多个资源封装成一个资源。一次拿够。
线程A,需要资源 s1.s2 先拿s1 再拿s2

package cn.hncu.thread.deadLock.v2;

public class ThreadA implements Runnable{
    private S1 s1 = null;
    private S2 s2 = null;

    public ThreadA(S1 s1, S2 s2) {
        this.s1 = s1;
        this.s2 = s2;
    }

    @Override
    public void run() {
        System.out.println("ThreadA begin......");
        synchronized (s1) {
            System.out.println("ThreadA拿到对象锁1:"+s1.a);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadA睡醒,准备拿对象锁2...");
            synchronized (s2) {
                System.out.println("ThreadA手握对象锁1和锁2,进行工作..."+s2.a);
            }
        }
    }

}

线程B 也需要资源 s1 s2 先拿s2 再拿s1

package cn.hncu.thread.deadLock.v2;

public class ThreadB implements Runnable{
    private S1 s1 = null;
    private S2 s2 = null;

    public ThreadB(S1 s1, S2 s2) {
        this.s1 = s1;
        this.s2 = s2;
    }

    @Override
    public void run() {
        System.out.println("ThreadB begin......");
        synchronized (s2) {
            System.out.println("ThreadB拿到对象锁2:"+s2.a);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadB睡醒,准备拿对象锁1...");
            synchronized (s1) {
                System.out.println("ThreadB手握对象锁1和锁2,进行工作..."+s1.a);
            }
        }
    }

}

演示代码

package cn.hncu.thread.deadLock.v2;

public class Demo2 {
    public static void main(String[] args) {
        S1 s1 = new S1();
        S2 s2 = new S2();

        Thread b = new Thread( new ThreadB(s1,s2) );
        Thread a = new Thread( new ThreadA(s1, s2) );

        b.start();
        a.start();
    }
}

class S1{
    public int a=1;
}
class S2{
    public int a=2;
}

结果
这里写图片描述
然后互相等待死锁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值