Java locks: 通过列表交出手锁

Java locks: Hand over hand locking through list

我正在尝试了解 java.util.concurrent.locks 库,并希望通过列表实现 运行 的两个线程,而第二个线程不应超过(领先)第一个线程。具体来说,我想实现手动锁定。

我写了下面的代码,但是不起作用。两个线程运行遍历链表后,节点在某一点后取值41。这意味着第二个线程在第一个线程之前编辑了它们。我在谷歌上搜索了很多,也看过类似的问题,但仍然无法弄清楚。非常感谢您的帮助,谢谢!!

import java.util.concurrent.locks.ReentrantLock;

class 主 {

public static void main(String[] args) throws InterruptedException {
    // Generate List
    Node first = new Node();
    Node current = first;
    for(int i = 0; i < 50; i++) {
        current.next = new Node();
        current = current.next;
    }

    // run Threads
    FirstThread a = new FirstThread(first);
    SecondThread b = new SecondThread(first);
    a.start();
    b.start();
    a.join();
    b.join();

    // Print result
    first.print();
}

}

class FirstThread 扩展线程 {

Node current;

FirstThread(Node start) {
    this.current = start;
}

public void run() {
    // =================> HAND OVER HAND LOCKING <=================
    current.lock.lock();
    while(current.next != null) {
        current.value = 41;
        current.next.lock.lock();
        current.lock.unlock();
        current = current.next;
    }
    current.value = 41;
    current.lock.unlock();
}

}

class SecondThread 扩展线程 {

Node current;

SecondThread(Node start) {
    current = start;
}

public void run() {
    while(current != null) {
        current.value++;
        current = current.next;
    }
}

}

class节点{

ReentrantLock lock;
Node next;
int value;

Node() {
    lock = new ReentrantLock();
    next = null;
    value = 0;
}

public void print() {
    Node current = this;
    while(current != null) {
        System.out.print(current.value + " ");
        current = current.next;
    }
    System.out.println();
}

}

PS:我知道如果线程被中断我实际上应该插入 try 和 finally 块但不知道在哪里所以只是忽略了那个事件。

看来您可能不明白 Lock 是什么。

一个Lock对象可以被某些人拥有(a.k.a., 锁定)线程,或者它可以是可用(a.k.a,解锁)。

当锁 l 不被任何线程拥有时,调用 l.lock() 会将其更改为由调用线程拥有,然后它会立即 return;但是如果 l 被其他线程拥有,那么 l.lock() 线程将等待(a.k.a。,它会 阻塞 )直到另一个线程通过调用 l.unlock().

释放其所有权

一个锁永远不能被多个线程拥有,并且 l.lock() 不会 return 直到调用线程成为所有者。

这就是锁的全部内容。*

您的 "first thread" 取得并释放了列表中锁的所有权,但您的 "second thread" 完全忽略了这些锁。

唯一会阻止 "second thread" 超越 "first thread" 的是,如果第二个线程在尝试拥有相同的锁对象时被阻塞。

另外,您需要一些机制来防止 "second thread" 在 "first thread" 运行 之前从列表开始。不能保证线程 运行 的顺序与您 start() 它们的顺序相同。


*"memory visibility" 除外,但那是另外一回事了。