分享

java并发(十七)重入锁死

 roydocs 2015-04-15
重入锁死与死锁和嵌套管程锁死非常相似。当一个线程重新获取锁,读写锁或其他不可重入的同步器时,就可能发生重入锁死。可重入的意思是线程可以重复获得它已经持有的锁。Java的synchronized块是可重入的。因此下面的代码是没问题的:



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

Java代码 复制代码 收藏代码
  1. public class Reentrant{  
  2.     public synchronized outer(){  
  3.         inner();  
  4.     }  
  5.     public synchronized inner(){  
  6.         //do something  
  7.     }  
  8. }  


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



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

Java代码 复制代码 收藏代码
  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.     public synchronized void unlock(){  
  11.         isLocked = false;  
  12.         notify();  
  13.     }  
  14. }  


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



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


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


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



重入锁的实现

Java代码 复制代码 收藏代码
  1. public class Lock {  
  2.     boolean isLocked = false;  
  3.     Thread lockedBy = null;  
  4.     int lockedCount = 0;  
  5.   
  6.     public synchronized void lock() throws InterruptedException {  
  7.         Thread callingThread = Thread.currentThread();  
  8.         while (isLocked && lockedBy != callingThread) {  
  9.             wait();  
  10.         }  
  11.         isLocked = true;  
  12.         lockedCount++;  
  13.         lockedBy = callingThread;  
  14.     }  
  15.   
  16.     public synchronized void unlock() {  
  17.         if (Thread.currentThread() == this.lockedBy) {  
  18.             lockedCount--;  
  19.             if (lockedCount == 0) {  
  20.                 isLocked = false;  
  21.                 notify();  
  22.             }  
  23.         }  
  24.     }  
  25. }  



 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多