2016-12-11 31 views
1

我试图在Java中使用ReentrantLock实现手动锁定,这是在LinkedList的Node类中初始化的,但我似乎有死锁我不知道如何解决它。任何帮助,将不胜感激。解决在Java中手动锁定链接列表中的死锁

// Insert value for key. 
public boolean add(K key, V value) { 
    // Require key != null and value != null 
    // Get hash code 
    int hash = key.hashCode(); 
    Node pred = null, curr = null; 

    try { 
     pred = head; 
     pred.lock.lock(); 
     curr = pred.next; 
     curr.lock.lock(); 

     while(curr.hash <= hash) { 
      if(key.equals(curr.key)) { // key present, update value 
       curr.value = value; 
       return false; 
      } 
      pred = curr; 
      pred.lock.lock(); 
      curr = curr.next; 
      curr.lock.lock(); 
     } 

     // key not present 
     Node node = new Node(hash, key, value); 
     node.next = pred.next; 
     pred.next = node; 

     return true; 
    } finally { 
     curr.lock.unlock(); 
     pred.lock.unlock(); 
    } 
} 
// Remove key/value pair 
public boolean remove(K key) { 
    // Require key != null 
    // Get hash code 
    int hash = key.hashCode(); 
    Node pred = null, curr = null; 

    try { 
     // Predecessor node 
     pred = this.head; 
     pred.lock.lock(); 
     //Current node 
     curr = pred.next; 
     curr.lock.lock(); 

     // traversing list 
     while(curr.hash <= hash) { 
      if(key.equals(curr.key)) { // key present, update value 
       pred.next = curr.next; 
       return true; 
      } 
      pred.lock.unlock(); 
      pred = curr; 
      curr = curr.next; 
      curr.lock.lock(); 
     } 

     // key not found 
     return false; 
    }finally { 
     curr.lock.unlock(); 
     pred.lock.unlock(); 
    } 
} 
+1

它看起来像是在while循环中锁定节点,并且您没有在添加方法中释放它们。 – hal

+0

http://cs.oswego.edu/pipermail/concurrency-interest/2007-April/004076.html –

回答

2

在add循环里面的while循环中,实际上有几个问题。

  1. 您的pred节点未被解锁。
  2. 您将curr节点锁定两次。

pred节点如何解锁?

pred = curr; 
pred.lock.lock(); 

所以在这里,你覆盖pred节点的本地参考,现在predcurr都指向同一个节点。因此,在覆盖pred参考之前,您需要确保您将该节点解锁。

curr节点如何锁定两次?

pred = curr; 
pred.lock.lock(); 

再次,同样的原因如上。 pred与您的curr位于同一节点,并且您已在方法开始时锁定了curr

所以调用pred.lock.lock()是你的死锁发生的地方。

它应该阅读:

pred.lock.unlock(); 
pred = curr; 
curr = curr.next; 
curr.lock.lock(); 
0

while循环有两个锁语句,而它应该是一个解锁(的预计值)和(更新现有的)锁。

请通过电子邮件与您的讲师联系。