杰神之Java多线程与死锁

原创 2018年02月06日 21:45:18

多线程卖火车票问题:

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.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java 多线程同步与死锁

在多线程中如何找到安全问题所在: 1,明确哪些代码是多线程运行代码 2,明确共享数据 3,明确多线程运行代码中哪些代码是操作共享数据的 静态的同步方法中,使用锁是该方法所在类的字节码文...
  • pjz90
  • pjz90
  • 2013年03月10日 14:51
  • 6022

Java多线程 线程同步与死锁

1.线程同步多线程引发的安全问题一个非常经典的案例,银行取钱的问题。假如你有一张银行卡,里面有5000块钱,然后你去银行取款2000块钱。正在你取钱的时候,取款机正要从你的5000余额中减去2000的...
  • kong_gu_you_lan
  • kong_gu_you_lan
  • 2017年02月25日 15:47
  • 832

java线程安全与死锁

线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。 出现线程安全问题的根本原因: 1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。 2. 有多个语句操作了共...
  • oguro
  • oguro
  • 2016年11月24日 20:10
  • 798

Java多线程中如何避免死锁

在Java中如何避免死锁,多线程开发时,经常会遇到这样的问题,什么是死锁,简单的说就是两个或多个线程,等待对方释放某个资源而卡死的情况...
  • yin1031468524
  • yin1031468524
  • 2017年02月15日 16:16
  • 1180

(十四)java多线程之死锁

本人邮箱: kco1989@qq.com 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kco github: https://github.com/...
  • tianshi_kco
  • tianshi_kco
  • 2016年10月31日 22:11
  • 534

《java并发编程实战》读书笔记——避免死锁的发生

我们使用加锁机制来确保线程安全,但如果过度地使用加锁,则可能导致锁顺序死锁。当一个线程永远地持有一个锁,并且其他线程都尝试获得这个锁时,那么他们将永远被阻塞。 在数据库系统的设中考虑了检测死锁以及从...
  • Great_Smile
  • Great_Smile
  • 2015年03月25日 13:50
  • 825

Java多线程产生死锁的原因和解决方法

一般造成死锁必须同时满足如下4个条件:  1,互斥条件:线程使用的资源必须至少有一个是不能共享的;  2,请求与保持条件:至少有一个线程必须持有一个资源并且正在等待获取一个当前被其它线程持有的资源; ...
  • hongtashan11
  • hongtashan11
  • 2011年05月24日 20:11
  • 1400

多线程同步与死锁深入分析

多线程同步与死锁深入分析 前言 在多线程开发中,同步与死锁是非常重要的,在本篇文章中,读者将会明白一下几点: 1、哪里需要同步 2、如何实现同步 3、以及实现同步之后会有哪些副作用 例子 ...
  • yangwenxue_admin
  • yangwenxue_admin
  • 2016年04月10日 17:53
  • 1875

杰神之Java第一课

Java初识
  • lyj243719866
  • lyj243719866
  • 2017年12月27日 19:50
  • 156

杰神之Java多线程基础概念和实现多线程

线程与进程 线程:进程中负责程序执行的执行单元 线程本身依靠程序进行运行 线程是程序中的顺序控制流,只能使用分配给程序的资源和环境 进程:执行中的程序 一个进程至少包含一个线程 单线程:程序...
  • lyj243719866
  • lyj243719866
  • 2018年02月05日 21:03
  • 16
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:杰神之Java多线程与死锁
举报原因:
原因补充:

(最多只允许输入30个字)