Java——死锁

死锁

多线程安全问题?

  1. 多个线程共享相同的数据

  2. 多个线程同时修改共享数据

解决方案: 同步, 同步方法, 同步代码

带来新的问题:

​ 1) 效率低: 如果多个线程调用同步方法,或者是同步代码块, 只能有一个线程获取对象锁, 才能执行方法,代码块,其他线程在外面阻塞,等到得到对象锁的线程释放这个对象锁, 同步阻塞

​ 2) 同步容易造成死锁

产生死锁的条件:

​ 1> 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用

​ 2> 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。

​ 3> 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占用。 线程获取锁对象不是一个

​ 4> 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路 多个线程 获取锁的顺序是刚好反的: 线程1: 获取锁顺序: p1-p2 线程2 获取锁顺序: p2-p1

死锁产生的条件上面4个条件缺一不可的

解决死锁的方案: 只要打破上面4个条件任何一个, 死锁不成立

package com.fs.threadDemo;

/**
 * 模拟一个死锁
 */
public class DeadThread {
    private Object objA = new Object();// 锁对象
    private Object objB = new Object();// 锁对象
    private boolean flag = true;// 设置获取锁的顺序: true: objA-objB
                                // false: objB-objA


    public void test(){
        if(flag){ //true: objA-objB
            synchronized (objA){
                System.out.println(Thread.currentThread().getName()+":获取到objA的锁");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //写在内部, 表示没有释放objA锁, 再去获取objB锁
                synchronized (objB){
                    System.out.println(Thread.currentThread().getName()+":获取到objB的锁");
                }
            }


            //获取objB对象锁,  写在外面,表示先释放objA锁, 再去获取objB锁
            /*synchronized (objB){

            }*/

        }else{//false: objB-objA
            synchronized (objB){
                System.out.println(Thread.currentThread().getName()+":获取到objB的锁");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (objA){
                    System.out.println(Thread.currentThread().getName()+":获取到objA的锁");
                }

            }

        }
    }

    public void changeFlag(boolean flag){
        this.flag = flag;
    }

}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        //创建DeadThread对象
        DeadThread dt = new DeadThread();

        //创建两个线程
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
               dt.test();
            }
        },"t1");
        //启动线程
        t1.start();  //执行 test()

        Thread.sleep(100); //让当前线程睡眠, main线程睡眠

        //dt.changeFlag(false); //main线程先抢到资源,  flag = false;

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                dt.test();
            }
        },"t2");

        //启动线程
        t2.start();
    }
}

开发过程中,一定避免出现死锁

常用类,集合,IO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值