首页 > 其他 > 详细

重入锁死

时间:2017-04-13 21:02:10      阅读:242      评论:0      收藏:0      [点我收藏+]

可重入锁:自己可以再次获取自己的内部的锁。比如有线程A获得了某对象的锁,此时这个时候锁还没有释放,当其再次想获取这个对象的锁的时候还是可以获取的,如果不可锁重入的话,就会造成死锁。Java的synchronized块是可重入的

可重入锁也支持在父子类继承的环境中,示例:

package com.dxz.sync;

public class Main {
    public int i = 10;

    public synchronized void operateMainMethod() {
        try {
            i--;
            System.out.println("main print i = " + i);
            Thread.sleep(1000);
        } catch (InterruptedException e) {

            e.printStackTrace();
        }
    }
}

子类:

package com.dxz.sync;

public class Sub extends Main {
    public synchronized void operateISubMethod() {
        try {
            while (i > 0) {
                i--;
                System.out.println("sub print i=" + i);
                Thread.sleep(100);
                this.operateMainMethod();
            }
        } catch (InterruptedException e) {

            e.printStackTrace();
        }
    }
}

线程:

package com.dxz.sync;

public class MyThread extends Thread {
    @Override
    public void run() {

        Sub sub = new Sub();
        sub.operateISubMethod();
    }
}

入口类:

package com.dxz.sync;

public class Test {

    public static void main(String[] args) {

        MyThread thread = new MyThread();
        thread.start();
    }

}

结果:

sub print i=9
main print i = 8
sub print i=7
main print i = 6
sub print i=5
main print i = 4
sub print i=3
main print i = 2
sub print i=1
main print i = 0

 

 

当一个线程重新获取读写锁或其他不可重入的同步器时,就可能发生重入锁死。可重入的意思是线程可以重复获得它已经持有的锁。Java的synchronized块是可重入的。

可重入锁:自己可以再次获取自己的内部的锁。比如有线程A获得了某对象的锁,此时这个时候锁还没有释放,当其再次想获取这个对象的锁的时候还是可以获取的,如果不可锁重入的话,就会造成死锁。

可重入锁也支持在父子类继承的环境中。

因此下面的代码是没问题的:

(译者注:这里提到的锁都是指的不可重入的锁实现,并不是Java类库中的Lock与ReadWriteLock类)

[java] view plain copy
 
 技术分享技术分享
  1. public class Reentrant{  
  2.     public synchronized outer(){  
  3.         inner();  
  4.     }  
  5.   
  6.     public synchronized inner(){  
  7.         //do something  
  8.     }  
  9. }  

 

 

注意outer()和inner()都声明为synchronized,这在Java中这相当于synchronized(this)块(译者注:这里两个方法是实例方法,synchronized的实例方法相当于在this上加锁,如果是static方法,则不然,更多阅读:哪个对象才是锁?)。如果某个线程调用了outer(),outer()中的inner()调用是没问题的,因为两个方法都是在同一个管程对象(即this)上同步的。如果一个线程持有某个管程对象上的锁,那么它就有权访问所有在该管程对象上同步的块。这就叫可重入。若线程已经持有锁,那么它就可以重复访问所有使用该锁的代码块。

下面这个锁的实现是不可重入的:

[java] view plain copy
 
 技术分享技术分享
  1. public class Lock{  
  2.     private boolean isLocked = false;  
  3.     public synchronized void lock()  
  4.         throws InterruptedException{  
  5.         while(isLocked){  
  6.             wait();  
  7.         }  
  8.         isLocked = true;  
  9.     }  
  10.   
  11.     public synchronized void unlock(){  
  12.         isLocked = false;  
  13.         notify();  
  14.     }  
  15. }  

 

如果一个线程在两次调用lock()间没有调用unlock()方法,那么第二次调用lock()就会被阻塞,这就出现了重入锁死。

避免重入锁死有两个选择:

  1. 编写代码时避免再次获取已经持有的锁
  2. 使用可重入锁

至于哪个选择最适合你的项目,得视具体情况而定。可重入锁通常没有不可重入锁那么好的表现,而且实现起来复杂,但这些情况在你的项目中也许算不上什么问题。无论你的项目用锁来实现方便还是不用锁方便,可重入特性都需要根据具体问题具体分析。

重入锁死

原文:http://www.cnblogs.com/duanxz/p/6705886.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!