美文网首页
Java死锁示例

Java死锁示例

作者: nzdxwl | 来源:发表于2019-11-24 09:00 被阅读0次

    以下是Java中死锁的两个示例,一个是同步代码块嵌套,一个是同步方法互相调用。

    public class DeadLockDemo {
        
        static void sleep(int seconds) {
            try {
                TimeUnit.SECONDS.sleep(seconds);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        /* 示例一:同步代码块嵌套 */
        static void demo1() {
            //相当于资源1和资源2
            Integer a1 = new Integer(1); 
            Integer a2 = new Integer(2);
            //两个次序相反的迭代器
            Iterator<Integer> it = Arrays.asList(a1,a2).iterator();
            Iterator<Integer> it2 = Arrays.asList(a2,a1).iterator();
            //两个线程同时执行
            new Thread(()-> {new DeadLockDemo().accessResource(it);}).start();
            new Thread(()-> {new DeadLockDemo().accessResource(it2);}).start();
        }
        
        //demo1示例所用方法,传入一个资源迭代器,获取每个资源后上锁并迭代处理后续资源
        public void accessResource(Iterator it) {
            if(it.hasNext()) {
                Object o = it.next();
                System.out.println(Thread.currentThread().getName() + " --- waiting for lock ---" + o);
                synchronized(o) {
                    System.out.println(Thread.currentThread().getName() + " --- hold lock ---" + o);
                    sleep(2);
                    accessResource(it);             
                }
            }
        }
        
        /* 示例二:互相调用  */
        static void demo2() {
            DeadLockDemo mdl = new DeadLockDemo();
            ClassA a = mdl.new ClassA();
            ClassB b = mdl.new ClassB();
            //一个线程调用a的同步方法,并传入b,在a方法中调用b的同步方法
            new Thread(()-> {a.handleClassB(b);}).start();
            //另外个线程则调用b的同步方法,传入a,在b方法中调用a的同步方法
            new Thread(()-> {b.handleClassA(a);}).start();
        }
        //同步方法中休眠1秒钟使得两个线程都有足够的时间获取到调用类的锁,否则可能a和b的锁都被一个线程获得,这样两个线程先后都能完成不会死锁
        class ClassA {
            public synchronized void handleClassB(ClassB b) {
                System.out.println("A handle B...");
                sleep(1); 
                b.doSomething();
            }       
            public synchronized void doSomething() { System.out.println("A processing");}
        }
    
        class ClassB{
            public synchronized void handleClassA(ClassA a) {
                System.out.println("B handle A...");
                sleep(1);
                a.doSomething();
            }       
            public synchronized void doSomething() {System.out.println("B processing"); }
        }   
    
        public static void main(String[] args) {
    //      demo1();
            demo2();
        }
    

    示例说明

    同步代码块嵌套

    这个例子是假设线程A要处理一系列资源,假设资源按照1,2,3的顺序保存在列表中,线程A调用同步方法逐个获取资源,并加锁后进行处理,如果资源未处理完,则进行迭代操作;那么如果有线程B也是要处理资源,获得的资源列表中包含线程A处理的资源,并且顺序与线程A相反,当线程B也进行同样的操作时,那么就有可能发生死锁。

    同步方法互相调用

    这个例子是线程1调用类A实例的同步方法,获得类A实例的锁,并在同步方法中调用类B的同步方法,
    与此同时,线程2则调用类B实例的同步方法,获得类B实例的锁,并在同步方法中调用类A的同步方法;当两个线程都获得第一个锁时,再去获取第二个锁就产生了死锁。下面例子用同个类的方法互调来产生死锁,原理与示例二一样,代码相对简洁但没示例二的好理解,且一旦只有一个线程获得两个锁时,会出现栈溢出错误。

    /* 同类互调 */
        static void demo3() {
            DeadLockDemo mdl1 = new DeadLockDemo();
            DeadLockDemo mdl2 = new DeadLockDemo();
            new Thread(()->{mdl1.processOther(mdl2);}).start();
            new Thread(()->{mdl2.processOther(mdl1);}).start();     
        }
        
        public synchronized void processOther(DeadLockDemo mdl) {
            System.out.println(Thread.currentThread().getName() + ": hold " + this + "'s lock...");
            sleep(1);
            mdl.processOther(this);
        }
    

    相关文章

      网友评论

          本文标题:Java死锁示例

          本文链接:https://www.haomeiwen.com/subject/zimcwctx.html