我正在尝试理解java.util.concurrent.locks库并想要实现两个运行列表的线程,而第二个线程不应该超越(带头)第一个线程。具体来说,我想实现手动锁定。
我写了下面的代码,但是没有用。在两个线程遍历列表之后,节点在某个点之后取值41。这意味着第二个线程在第一个线程编辑之前编辑了它们。我google了很多,也看了类似的问题,但仍然无法弄明白。非常感谢你的帮助,谢谢!!
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扩展了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();
}
}
类SecondThread扩展了线程{
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();
}
}
PS:我知道我应该插入try和finally块,如果线程被中断但不知道在哪里,那么只是忽略了那个事件。
答案 0 :(得分:0)
看起来你可能不明白Lock
是什么。
Lock
对象可以由某个线程拥有(又名,已锁定),也可以可用(又名,解锁)。
当锁l
不属于任何线程时,对l.lock()
的调用会将其更改为由调用线程拥有,然后它将立即返回;但如果l
由其他某个线程拥有,那么l.lock()
线程将等待(也就是说,阻塞),直到另一个线程通过调用{{1}释放其所有权}}
锁永远不会被多个线程拥有,l.unlock()
在调用线程为所有者之前不会返回。
基本上只有锁定。*
你的&#34;第一个帖子&#34;获取并释放列表中锁的所有权,但是您的第二个线程&#34;完全忽略了锁。
唯一会阻止&#34;第二个线程&#34;从超越&#34;第一线程&#34;如果第二个线程在尝试拥有相同的锁定对象时被阻止。
另外,你需要一些机制来阻止&#34;第二个线程&#34;从开始之前第一个线程&#34;运行。不保证线程的运行顺序与l.lock()
它们相同。
*除了&#34;内存可见性&#34;,但这是另一个主题。