One thread calculates some data that takes about 1GB of RAM and another thread only reads this data. What is the best way to implement this?
一个线程计算一些需要大约1GB RAM的数据,另一个线程只读取这些数据。实现这个的最佳方法是什么?
use std::thread;
use std::time::Duration;
fn main() {
let mut shared: i32 = 0; // will be changed to big structure
thread::spawn(move || {
loop {
shared += 1;
println!("write shared {}", shared);
thread::sleep(Duration::from_secs(2));
}
});
thread::spawn(move || {
loop {
thread::sleep(Duration::from_secs(1));
println!("read shared = ???"); // <---------------- ????
}
});
thread::sleep(Duration::from_secs(4));
println!("main");
}
You can run this code online (play.rust-lang.org)
您可以在线运行此代码(play.rust-lang.org)
1 个解决方案
#1
2
The code and your statements don't really make sense together. For example, there's nothing that prevents the second thread from finishing before the first thread ever has a chance to start. Yes, I see the sleeps, but sleeping is not a viable concurrency solution.
代码和你的陈述并没有真正有意义。例如,在第一个线程有机会启动之前,没有任何东西阻止第二个线程完成。是的,我看到了睡眠,但睡眠不是一个可行的并发解决方案。
For the question as asked, I'd use a channel. This allows one thread to produce a value and then transfer ownership of that value to another thread:
对于问题,我会使用一个频道。这允许一个线程生成一个值,然后将该值的所有权转移到另一个线程:
use std::thread;
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
let a = thread::spawn(move || {
let large_value = 1;
println!("write large_value {}", large_value);
tx.send(large_value).expect("Unable to send");
});
let b = thread::spawn(move || {
let large_value = rx.recv().expect("Unable to receive");
println!("read shared = {}", large_value);
});
a.join().expect("Unable to join a");
b.join().expect("Unable to join b");
println!("main");
}
For the code as presented, there's really no other options besides a Mutex
or a RwLock
. This allows one thread to mutate the shared value for a while, then the other thread may read it for a while (subject to the vagaries of the OS scheduler):
对于所呈现的代码,除了Mutex或RwLock之外,实际上没有其他选项。这允许一个线程突变共享值一段时间,然后另一个线程可能会读取它一段时间(受操作系统调度程序的变幻莫测):
use std::thread;
use std::time::Duration;
use std::sync::{Arc, Mutex};
fn main() {
let shared = Arc::new(Mutex::new(0));
let shared_1 = shared.clone();
thread::spawn(move || {
loop {
let mut shared = shared_1.lock().expect("Unable to lock");
*shared += 1;
println!("write large_value {}", *shared);
}
});
thread::spawn(move || {
loop {
let shared = shared.lock().expect("Unable to lock");
println!("read shared = {}", *shared);
}
});
thread::sleep(Duration::from_secs(1));
println!("main");
}
None of this is particularly unique to Rust; channels are quite popular in Go and Clojure and mutexes have existed for A Very Long Time. I'd suggest checking out any of the numerous beginner's guides on the Internet for multithreading and the perils therein.
这些都不是Rust特有的独特之处;频道在Go和Clojure中很受欢迎,互斥体已存在很长时间。我建议查看互联网上众多初学者指南中的任何一个,以了解多线程和其中的危险。
#1
2
The code and your statements don't really make sense together. For example, there's nothing that prevents the second thread from finishing before the first thread ever has a chance to start. Yes, I see the sleeps, but sleeping is not a viable concurrency solution.
代码和你的陈述并没有真正有意义。例如,在第一个线程有机会启动之前,没有任何东西阻止第二个线程完成。是的,我看到了睡眠,但睡眠不是一个可行的并发解决方案。
For the question as asked, I'd use a channel. This allows one thread to produce a value and then transfer ownership of that value to another thread:
对于问题,我会使用一个频道。这允许一个线程生成一个值,然后将该值的所有权转移到另一个线程:
use std::thread;
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
let a = thread::spawn(move || {
let large_value = 1;
println!("write large_value {}", large_value);
tx.send(large_value).expect("Unable to send");
});
let b = thread::spawn(move || {
let large_value = rx.recv().expect("Unable to receive");
println!("read shared = {}", large_value);
});
a.join().expect("Unable to join a");
b.join().expect("Unable to join b");
println!("main");
}
For the code as presented, there's really no other options besides a Mutex
or a RwLock
. This allows one thread to mutate the shared value for a while, then the other thread may read it for a while (subject to the vagaries of the OS scheduler):
对于所呈现的代码,除了Mutex或RwLock之外,实际上没有其他选项。这允许一个线程突变共享值一段时间,然后另一个线程可能会读取它一段时间(受操作系统调度程序的变幻莫测):
use std::thread;
use std::time::Duration;
use std::sync::{Arc, Mutex};
fn main() {
let shared = Arc::new(Mutex::new(0));
let shared_1 = shared.clone();
thread::spawn(move || {
loop {
let mut shared = shared_1.lock().expect("Unable to lock");
*shared += 1;
println!("write large_value {}", *shared);
}
});
thread::spawn(move || {
loop {
let shared = shared.lock().expect("Unable to lock");
println!("read shared = {}", *shared);
}
});
thread::sleep(Duration::from_secs(1));
println!("main");
}
None of this is particularly unique to Rust; channels are quite popular in Go and Clojure and mutexes have existed for A Very Long Time. I'd suggest checking out any of the numerous beginner's guides on the Internet for multithreading and the perils therein.
这些都不是Rust特有的独特之处;频道在Go和Clojure中很受欢迎,互斥体已存在很长时间。我建议查看互联网上众多初学者指南中的任何一个,以了解多线程和其中的危险。