在Java中手动锁定链接列表解决死锁问题

时间:2016-12-11 15:43:29

标签: java multithreading concurrency locking

我尝试使用在LinkList的Node类中初始化的ReentrantLock在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();
    }
}

2 个答案:

答案 0 :(得分:2)

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

  1. 您的pred节点未解锁。
  2. 您锁定curr节点两次。
  3. 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();
    

答案 1 :(得分:0)

你的while循环有两个锁定语句,它应该是解锁(pred)和锁定(更新当前)。

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