Rust:应用程序陷入死锁。

huangapple go评论62阅读模式
英文:

Rust: application getting deadlocked

问题

I am new to rust and currently learning the concurrency chapter. In my current implementation I have created two traits namely StartThread(creates new thread inside start method which internally calls run method) and TerminateThread(for terminating thread; has two methods namely stop and wait). My implementation is currently getting deadlocked when stop method is called from main thread.

thread.rs

use std::sync::{Arc, Mutex};
use std::thread;

pub struct RunningThreadInterface<T> {
    pub instance: Arc<Mutex<T>>,
    pub thread_join_handle: thread::JoinHandle<()>,
}

pub trait StartThread<T> {
    fn start(self, thread_ID: String) -> RunningThreadInterface<T>;
    fn run(&mut self);
}

pub trait TerminateThread {
    fn stop(&mut self);
    fn wait(self);
}

NetworkReceiver.rs

use std::{thread, time};
use std::sync::{atomic::{AtomicBool, Ordering}, Arc, Mutex};

use crate::thread::*;

#[derive(Default)]
pub struct NetworkReceiverThread {
    thread_ID: String,
    terminate_flag: AtomicBool,
}

impl NetworkReceiverThread {
    pub fn new() -> NetworkReceiverThread {
        NetworkReceiverThread {
            thread_ID: String::from(""),
            terminate_flag: AtomicBool::new(false),
        }
    }
}

impl StartThread<NetworkReceiverThread> for NetworkReceiverThread {
    fn start(mut self, thread_ID: String) -> RunningThreadInterface<NetworkReceiverThread> {
        self.thread_ID = thread_ID.clone();

        let network_receiver = Arc::new(Mutex::new(self));
        RunningThreadInterface {
            instance: Arc::clone(&network_receiver),
            thread_join_handle: thread::Builder::new().name(thread_ID).spawn(move || network_receiver.lock().unwrap().run()).ok().unwrap(),
        }
    }

    fn run(&mut self) {
        // let mut buff: [u8; 2048] = [0; 2048];

        while !self.terminate_flag.load(Ordering::SeqCst) {
            // receive network data and put into queue(will be processed by processor thread)
            println!("receiver thread");
            std::thread::sleep(time::Duration::from_secs(1));
        }
    }
}

impl TerminateThread for RunningThreadInterface<NetworkReceiverThread> {
    fn stop(&mut self) {
        self.instance.lock().unwrap().terminate_flag.store(true, Ordering::SeqCst);
    }

    fn wait(self) {
        self.thread_join_handle.join();
    }
}

main.rs

mod thread;
mod NetworkReceiver;

use std::time;
use thread::*;
use NetworkReceiver::NetworkReceiverThread;

fn main() {
    let network_receiver = NetworkReceiverThread::new();

    let mut network_receiver: RunningThreadInterface<NetworkReceiverThread> = network_receiver.start(String::from("NT"));

    std::thread::sleep(time::Duration::from_secs(5));

    network_receiver.stop();
    network_receiver.wait();
}

cargo.toml

[package]
name = "ThreadChapter"
version = "0.1.0"
edition = "2021"

This is the translated code you provided.

英文:

I am new to rust and currently learning the concurrency chapter. In my current implementation I have created two traits namely StartThread(creates new thread inside start method which internally calls run method) and TerminateThread(for terminating thread; has two methods namely stop and wait). My implementation is currently getting deadlocked when stop method is called from main thread.

thread.rs

use std::sync::{Arc, Mutex};
use std::thread;

pub struct RunningThreadInterface&lt;T&gt; {
    pub instance: Arc&lt;Mutex&lt;T&gt;&gt;,
    pub thread_join_handle: thread::JoinHandle&lt;()&gt;,
}

pub trait StartThread&lt;T&gt; {
    fn start(self, thread_ID: String) -&gt; RunningThreadInterface&lt;T&gt;;
    fn run(&amp;mut self);
}

pub trait TerminateThread {
    fn stop(&amp;mut self);
    fn wait(self);
}

NetworkReceiver.rs

use std::{thread, time};
use std::sync::{atomic::{AtomicBool, Ordering}, Arc, Mutex};

use crate::thread::*;

#[derive(Default)]
pub struct NetworkReceiverThread {
    thread_ID: String,
    terminate_flag: AtomicBool,
}

impl NetworkReceiverThread {
    pub fn new() -&gt; NetworkReceiverThread {
        NetworkReceiverThread {
            thread_ID: String::from(&quot;&quot;),
            terminate_flag: AtomicBool::new(false),
        }
    }
}

impl StartThread&lt;NetworkReceiverThread&gt; for NetworkReceiverThread {
    fn start(mut self, thread_ID: String) -&gt; RunningThreadInterface&lt;NetworkReceiverThread&gt; {
        self.thread_ID = thread_ID.clone();

        let network_receiver = Arc::new(Mutex::new(self));
        RunningThreadInterface {
            instance: Arc::clone(&amp;network_receiver),
            thread_join_handle: thread::Builder::new().name(thread_ID).spawn(move || network_receiver.lock().unwrap().run()).ok().unwrap(),
        }
    }

    fn run(&amp;mut self) {
        // let mut buff: [u8; 2048] = [0; 2048];

        while !self.terminate_flag.load(Ordering::SeqCst) {
            // receive network data and put into queue(will be processed by processor thread)
            println!(&quot;receiver thread&quot;);
            std::thread::sleep(time::Duration::from_secs(1));
        }
    }
}

impl TerminateThread for RunningThreadInterface&lt;NetworkReceiverThread&gt; {
    fn stop(&amp;mut self) {
        self.instance.lock().unwrap().terminate_flag.store(true, Ordering::SeqCst);
    }

    fn wait(self) {
        self.thread_join_handle.join();
    }
}

main.rs

mod thread;
mod NetworkReceiver;

use std::time;
use thread::*;
use NetworkReceiver::NetworkReceiverThread;

fn main() {
    let network_receiver = NetworkReceiverThread::new();

    let mut network_receiver: RunningThreadInterface&lt;NetworkReceiverThread&gt; = network_receiver.start(String::from(&quot;NT&quot;));

    std::thread::sleep(time::Duration::from_secs(5));

    network_receiver.stop();
    network_receiver.wait();
}

cargo.toml

[package]
name = &quot;ThreadChapter&quot;
version = &quot;0.1.0&quot;
edition = &quot;2021&quot;

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

答案1

得分: 2

The lock in start() is a temporary, and it is dropped at the end of the statement. So the whole time run() is running the lock is held, and when you're trying to acquire it, it is still held.

start()中的锁是临时的,在语句结束时会被释放。因此,在run()运行的整个过程中,锁一直被持有,当你尝试获取它时,它仍然被持有。

The solution depends on your requirements. In this simple example, there is no need to use Mutex at all, since AtomicBool allows assignments via shared references:

解决方案取决于您的需求。在这个简单的示例中,根本不需要使用Mutex,因为AtomicBool允许通过共享引用进行赋值:

thread.rs:

use std::sync::Arc;
use std::thread;

pub struct RunningThreadInterface<T> {
    pub instance: Arc<T>,
    pub thread_join_handle: thread::JoinHandle<()>,
}

pub trait StartThread<T> {
    fn start(self, thread_ID: String) -> RunningThreadInterface<T>;
    fn run(&self);
}

pub trait TerminateThread {
    fn stop(&mut self);
    fn wait(self);
}

NetworkReceiver.rs:

use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};
use std::{thread, time};

use crate::thread::*;

#[derive(Default)]
pub struct NetworkReceiverThread {
    thread_ID: String,
    terminate_flag: AtomicBool,
}

impl NetworkReceiverThread {
    pub fn new() -> NetworkReceiverThread {
        NetworkReceiverThread {
            thread_ID: String::from(""),
            terminate_flag: AtomicBool::new(false),
        }
    }
}

impl StartThread<NetworkReceiverThread> for NetworkReceiverThread {
    fn start(mut self, thread_ID: String) -> RunningThreadInterface<NetworkReceiverThread> {
        self.thread_ID = thread_ID.clone();

        let network_receiver = Arc::new(self);
        RunningThreadInterface {
            instance: Arc::clone(&network_receiver),
            thread_join_handle: thread::Builder::new()
                .name(thread_ID)
                .spawn(move || network_receiver.run())
                .ok()
                .unwrap(),
        }
    }

    fn run(&self) {
        // let mut buff: [u8; 2048] = [0; 2048];

        while !self.terminate_flag.load(Ordering::SeqCst) {
            // receive network data and put into queue(will be processed by processor thread)
            println!("receiver thread");
            std::thread::sleep(time::Duration::from_secs(1));
        }
    }
}

impl TerminateThread for RunningThreadInterface<NetworkReceiverThread> {
    fn stop(&mut self) {
        self.instance.terminate_flag.store(true, Ordering::SeqCst);
    }

    fn wait(self) {
        self.thread_join_handle.join();
    }
}

Please let me know if you need any further assistance or specific translations.

英文:

The lock in start() is a temporary, and it is dropped at the end of the statement. So the whole time run() is running the lock is held, and when you're trying to acquire it it is still held.

The solution depends on your requirements. In this simple example, there is no need to use Mutex at all, since AtomicBool allows assignments via shared references:

thread.rs:

use std::sync::Arc;
use std::thread;

pub struct RunningThreadInterface&lt;T&gt; {
    pub instance: Arc&lt;T&gt;,
    pub thread_join_handle: thread::JoinHandle&lt;()&gt;,
}

pub trait StartThread&lt;T&gt; {
    fn start(self, thread_ID: String) -&gt; RunningThreadInterface&lt;T&gt;;
    fn run(&amp;self);
}

pub trait TerminateThread {
    fn stop(&amp;mut self);
    fn wait(self);
}

NetworkReceiver.rs:

use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};
use std::{thread, time};

use crate::thread::*;

#[derive(Default)]
pub struct NetworkReceiverThread {
    thread_ID: String,
    terminate_flag: AtomicBool,
}

impl NetworkReceiverThread {
    pub fn new() -&gt; NetworkReceiverThread {
        NetworkReceiverThread {
            thread_ID: String::from(&quot;&quot;),
            terminate_flag: AtomicBool::new(false),
        }
    }
}

impl StartThread&lt;NetworkReceiverThread&gt; for NetworkReceiverThread {
    fn start(mut self, thread_ID: String) -&gt; RunningThreadInterface&lt;NetworkReceiverThread&gt; {
        self.thread_ID = thread_ID.clone();

        let network_receiver = Arc::new(self);
        RunningThreadInterface {
            instance: Arc::clone(&amp;network_receiver),
            thread_join_handle: thread::Builder::new()
                .name(thread_ID)
                .spawn(move || network_receiver.run())
                .ok()
                .unwrap(),
        }
    }

    fn run(&amp;self) {
        // let mut buff: [u8; 2048] = [0; 2048];

        while !self.terminate_flag.load(Ordering::SeqCst) {
            // receive network data and put into queue(will be processed by processor thread)
            println!(&quot;receiver thread&quot;);
            std::thread::sleep(time::Duration::from_secs(1));
        }
    }
}

impl TerminateThread for RunningThreadInterface&lt;NetworkReceiverThread&gt; {
    fn stop(&amp;mut self) {
        self.instance.terminate_flag.store(true, Ordering::SeqCst);
    }

    fn wait(self) {
        self.thread_join_handle.join();
    }
}

huangapple
  • 本文由 发表于 2023年5月14日 21:04:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76247628.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定