我试图了解 java.util.concurrent.locks 库,并希望实现两个通过列表运行的线程,而第二个线程不应超过(领先)第一个线程。具体来说,我想实现手动锁定。
我写了下面的代码,但不起作用。两个线程运行完列表后,节点在某个点之后取值 41。这意味着第二个线程在第一个线程之前编辑它们。我用谷歌搜索了很多,也看了类似的问题,但仍然无法弄清楚。我真的很感谢你的帮助,谢谢!
import java.util.concurrent.locks.ReentrantLock;
class Main {
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 extends Thread {
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 extends Thread {
Node current;
SecondThread(Node start) {
current = start;
}
public void run() {
while(current != null) {
current.value++;
current = current.next;
}
}
}
class Node {
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();
}
}
P.S.:我知道如果线程被中断,我实际上应该插入 try 和finally 块,但不知道在哪里,所以只是忽略了该事件。
看来您可能不明白
Lock
是什么。
Lock
对象可以由某个线程拥有(又名,锁定),也可以是可用(又名,解锁)。
当锁
l
不属于任何线程时,调用l.lock()
会将其更改为由调用线程拥有,然后立即返回;但如果 l
由某个其他线程拥有,则 l.lock()
线程将等待(又名,它将阻塞),直到另一个线程通过调用 l.unlock()
释放其所有权。
一把锁永远不能被多个线程拥有,并且
l.lock()
在调用线程成为所有者之前不会返回。
这基本上就是锁的全部内容。*
您的“第一个线程”获取并释放列表中锁的所有权,但您的“第二个线程”完全忽略这些锁。
阻止“第二个线程”超越“第一个线程”的唯一方法是,如果第二个线程在尝试拥有相同的锁对象时被阻塞。
此外,您还需要某种机制来防止“第二个线程”在“第一个线程”运行之前从列表中启动。不保证线程按照您 start()
它们的顺序运行。