杰神之Java多线程与死锁

多线程卖火车票问题:

public class Demo05 {
    public static void main(String[] args) {
        newThread 买票12306=new newThread();
        newThread 黄牛=new newThread();
        newThread 手机APP=new newThread();
        买票12306.start();
        黄牛.start();
        手机APP.start();
    }
}
class newThread extends Thread{
    private static int 票数=1000;
    private Object obj=new Object();
    public void run() {
        while(true) {
                if (票数<=0) {
                    break;
                }
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                票数-=1;
                System.out.println(Thread.currentThread().getName()+"    "+票数);
            }
        }
}

当多个线程同时访问一个数据时,很容易出现问题。为了避免这种情况出现,我们要保证线程同步互斥,就是指并发执行的多个线程,在同一时间内只允许一个线程访问共享数据。
Java中可以使用synchronized关键字来取得一个对象的同步锁。

// Object可以为任何对象,表示当前线程取得该对象的锁。
synchronized (Object) {
}

修改一下上面的案例,在run方法中加入同步锁:

public class Demo05 {
    public static void main(String[] args) {
        newThread 买票12306=new newThread();
        newThread 黄牛=new newThread();
        newThread 手机APP=new newThread();
        买票12306.start();
        黄牛.start();
        手机APP.start();
    }
}
class newThread extends Thread{
    private static int 票数=1000;
    private Object obj=new Object();
    public void run() {
        while(true) {
            synchronized(obj) {
                if (票数<=0) {
                    break;
                }
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                票数-=1;
                System.out.println(Thread.currentThread().getName()+"    "+票数);
            }
            //让线程放弃CPU资源
            Thread.yield();
        }
    }
}

死锁

同步锁虽好,但也要科学使用,不然就会发生死锁,何为死锁,就是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。
举个栗子,两个人面对面过独木桥,甲和乙都已经在桥上走了一段距离,即占用了桥的资源,甲如果想通过独木桥的话,乙必须退出桥面让出桥的资源,让甲通过,但是乙不服,为什么让我先退出去,我还想先过去呢,于是就僵持不下,导致谁也过不了桥,这就是死锁。

public class Demo07 {
    public static void main(String[] args) {
        new Thread() {
            private boolean isTrue=true;
            @Override
            public void run() {
                while(true) {
                    if(isTrue) {
                        synchronized (LockA.LOCK_A) {
                            System.out.println("if---LockA");
                            synchronized (LockB.LOCK_B) {
                                System.out.println("if---LockB");
                            }
                        }
                    }else {
                        synchronized (LockB.LOCK_B) {
                            System.out.println("else---LockB");
                            synchronized (LockA.LOCK_A) {
                                System.out.println("else---LockA");
                            }
                        }
                    }
                    isTrue=!isTrue;
                }
            }
        }.start();
        new Thread() {
            private boolean isTrue=true;
            @Override
            public void run() {
                while(true) {
                    if(isTrue) {
                        synchronized (LockA.LOCK_A) {
                            System.out.println("if---LockA");
                            synchronized (LockB.LOCK_B) {
                                System.out.println("if---LockB");
                            }
                        }
                    }else {
                        synchronized (LockB.LOCK_B) {
                            System.out.println("else---LockB");
                            synchronized (LockA.LOCK_A) {
                                System.out.println("else---LockA");
                            }
                        }
                    }
                    isTrue=!isTrue;
                }
            }
        }.start();
    }
}
class LockA{
    private LockA() {

    }
    //定义一个常量作为锁对象 不能修改也不能创建
    public static final LockA LOCK_A=new LockA();
}
class LockB{
    private LockB() {

    }
    public static final LockB LOCK_B=new LockB();
}

第一个线程锁住了资源1(
A一部分资源),第二个线程锁住了资源2(一部分资源),线程1企图锁住资源2(A让B释放资源,B不放),进入阻塞,线程2企图锁住资源1(B让A释放资源,A不放),进入阻塞,死锁了。
死锁的产生是有规律可循的,只有同时满足以下四个条件,死锁才会产生。
* 1.互斥条件:一个资源每次只能被一个进程使用。独木桥每次只能通过一个人。
* 2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  • 3.不剥夺条件: 进程已获得的资源,在未使用完之前,不能强行剥夺。

  • 4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

知道了死锁产生的必要条件,在开发中就很容易避免死锁问题了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值