Java锁:通过列表交手锁

问题描述 投票:0回答:1

我试图了解 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 块,但不知道在哪里,所以只是忽略了该事件。

java multithreading concurrency locking reentrantlock
1个回答
2
投票

看来您可能不明白

Lock
是什么。

Lock
对象可以由某个线程拥有(又名,锁定),也可以是可用(又名,解锁)。

当锁

l
不属于任何线程时,调用
l.lock()
会将其更改为由调用线程拥有,然后立即返回;但如果
l
由某个其他线程拥有,则
l.lock()
线程将等待(又名,它将阻塞),直到另一个线程通过调用
l.unlock()
释放其所有权。

一把锁永远不能被多个线程拥有,并且

l.lock()
在调用线程成为所有者之前不会返回。

这基本上就是锁的全部内容。*

您的“第一个线程”获取并释放列表中锁的所有权,但您的“第二个线程”完全忽略这些锁。

阻止“第二个线程”超越“第一个线程”的唯一方法是,如果第二个线程在尝试拥有相同的锁对象时被阻塞。

此外,您还需要某种机制来防止“第二个线程”在“第一个线程”运行之前从列表中启动。不保证线程按照您 start()

 它们的顺序运行。


*除了“内存可见性”,但那是一个完全不同的主题。

© www.soinside.com 2019 - 2024. All rights reserved.