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" 除外,但那是另外一回事了。
我正在尝试了解 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" 除外,但那是另外一回事了。