英文:
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<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"
# 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<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();
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论