【问题标题】:ReentrantLock - unlock() method doesn't seem to work with listsReentrantLock - unlock() 方法似乎不适用于列表
【发布时间】:2013-11-01 21:00:56
【问题描述】:

我正在编写一个必须以两种方式修改列表的程序。尽管此实现完美运行,但它无法让第二个线程获取锁:

Node head = new Node(new Object(), null);
public static ReentrantLock lock = new ReentrantLock();
...

boolean add(Object o){
    lock.lock();
    Node current = head;
    Node previous = head.next;

    if(head.next==null){
        head.addNext(new Node(o,null));
        return true;
    }
    while(!(current.next == null)){
        current=current.next;
        previous=previous.next;
    }
    current.addNext(new Node(o,null));
    lock.unlock();
    return true;    
}

也许有人知道这是为什么?

【问题讨论】:

  • 似乎有一个带有长度字段的链表似乎很奇怪......
  • 由于获取锁比您执行的操作要慢得多,如果每个列表而不是每个节点只有一个锁,代码会更快更简单。
  • 这是我的另一个错误,感谢您指出这一点。
  • @PeterLawrey 为什么在 X 个不同的锁上锁定 X 次(从不同时)比在 1 个锁上锁定 X 次(也从不同时)慢?
  • @rolfl 我不会多次获得相同的锁,但是多次获得一个锁仍然比获得许多锁要快,因为您可以获得良好的内存访问局部性。在整个操作过程中,我只需获得一次锁。

标签: java multithreading unlock reentrantlock


【解决方案1】:

有些代码分支永远不允许调用解锁。例如在添加

if(head.next==null){
    head.addNext(new Node(o,null));
    return true;
}

您无需解锁即可返回。您应该遵循lock try finally unlock 语义。

lock.lock();
try{
   ... do stuff 
   return true;
}finally{
   lock.unlock();
} 

【讨论】: