Rust无畏并发:允许编写没有细微BUG的代码,并在不引入新BUG的情况下易于重构
实现多线程的方式:使用Os的Api创建线程, 1:1模型,2.语言自己实现的线程, M:N模型
Rust标准库仅提供1:1线程模型,通过Thread::spawn创建新线程,参数为闭包(新线程中运行的代码
fn main() {
let a = || {
loop {
println!("我是子进程");
// 暂停两秒
thread::sleep(Duration::from_secs(2));
}
};
let son_thread = thread::spawn(a);
loop {
println!("我是父进程");
thread::sleep(Duration::from_secs(1));
}
// join干哈的我就不多说了
son_thread.join();
}
我是父进程
我是子进程
我是父进程
我是父进程
必报的子线程可以贡献同一作用域下的其他线程参数,这是闭包的特性哦应该没有忘记把。但是在多线程中我们还需要Move来传递参数 :
fn main() {
let data = String::from("我是主线程数据");
// let a = move || {
let a = || {
println!("获取主线程的数据: {}", data);
};
let son_thread = thread::spawn(a);
son_thread.join();
}
let a = || {
| ^^ may outlive borrowed value `data`
8 | println!("获取主线程的数据: {}", data);
| ---- `data` is borrowed here
这里的报错的意思指:我们在子线程中调用的这个数据可能在子线程运行完毕之前就被del了,Rust编译器连这都想到了确实很细致。我们如果一定要获得参数的化使用Move 获取此参数的所有权即可
消息传递是一种很流行的保证安全并发的线程通讯技术。线程彼此之间通过发送消息完成通讯。可以理解为Python中的携程
Rust 使用Channel(标准库提供)实现进程通讯。Channel包含发送端域接收单,调用发送端的方法就是发送数据,接收端会检查和接受收到的数据。如果发送,接受任意一端被丢弃,Channel就关闭了。
使用mpsc::channel创建Channel (多个生产者,一个消费者), 返回一个元组,一个发送端,一个接收端。
fn main() {
let (sender,receiver) = mpsc::channel();
let a = move || {
loop {
//返回Result, 有问题就甩Err
sender.send(String::from("Hello"));
// 这里如果上面发送的是变量的化,那所有权已经在receiver手里了
println!("获取主线程发送数据: Hello");
thread::sleep(Duration::from_secs(1));
}
};
let son_thread = thread::spawn(a);
loop {
// 阻塞当前线程知道Channel中有值送到, 发送端关闭则返回错误
let data = receiver.recv().unwrap();
println!("收到数据: {}",data);
}
son_thread.join();
}
收到数据: Hello
获取主线程发送数据: Hello
获取主线程发送数据: Hello
收到数据: Hello
对于发送者,我们可以使用克隆创建多个发送者,毕竟是多生产者单消费者
这一节讲的就是锁,利用Mutex
面向对象不是简单的有类有函数就OJBK了, 面向对象三大特性最少要保证吧:封装,继承,堕胎。关于Rust的面向对象特性其实是一个比较矛盾的存在。
trait对象其实更多像接口或抽象类定义,在我们上一张学了Box之后就可以采用Box进行泛化了。BOx进行泛化保证同一个Vec中可以存储不同类型, 这种派发与普通的trait泛形约束相比较属于动态派发,无法在编译时确定类型。对于这种trait,Rust限定了两条法则保证安全:
// 一个泛形的例子
use crate::type2::Name2;
trait whoami{
fn print_my_type(&self);
}
struct type1{
Name1:String,
}
impl whoami for type1 {
fn print_my_type(&self) {
println!("I'm type1");
}
}
enum type2{
Name2(Vec<String>),
}
impl whoami for type2 {
fn print_my_type(&self) {
println!("I'm type 2")
}
}
struct type_done_whoami_trait{
// 完成了vec的都可以放到type_vec中
type_vec:Vec<Box<dyn whoami>>,
}
impl type_done_whoami_trait{
fn new() -> type_done_whoami_trait{
let a = type1{ Name1: String::new()};
let c = type1{ Name1: String::new()};
let b = type2::Name2(vec![String::new()]);
type_done_whoami_trait {
type_vec: vec![Box::new(a),Box::new(b),Box::new(c)]
}
}
}
fn main() {
let c = type_done_whoami_trait::new();
for p in c.type_vec{
// 这里直接 p.print_my_type()也是可以的
(*p).print_my_type();
}
}
经典面向对象的模式不适合Rust,使用需谨慎哦