Rust在线运行

版本:

所属目录
点击了解高性能代码运行API
运行结果
教程手册
代码仓库
极速运行
终端运行
图形+终端

                        
以下是用户最新保存的代码
### VecDeque 复制测试 发布于:2024-04-23 09:37 ## 输入三个整数x,y,z,请把这三个数由小到大输出。 发布于:2024-03-03 11:45 # rust slice 发布于:2024-02-20 13:49 rust学习 发布于:2024-01-04 08:20 Rust hello world 发布于:2024-01-01 23:49 # Rust的常用迭代器适配器 ## map 可以用闭包将迭代器里的每个元素应用闭包里自定义的逻辑,从而生成处理后的元素迭代器,可以应用于数据处理与提取. ## filter 可以使用闭包过滤迭代器里的元素,只挑选出符合要求的元素组成新的迭代器返回。 ## fold ## zip ## chunks ## Chain ## all ## any ## windows ## cycle 发布于:2023-12-27 17:58 # 箱子、栈和堆 在 Rust 中,所有值默认都是栈分配的。通过创建 Box<T>,可以把值装箱(boxed)来使它在堆上分配。箱子(box,即 Box<T> 类型的实例)是一个智能指针,指向堆分配的 T 类型的值。当箱子离开作用域时,它的析构函数会被调用,内部的对象会被销毁,堆上分配的内存也会被释放。 被装箱的值可以使用 * 运算符进行解引用;这会移除掉一层装箱。 发布于:2023-12-27 17:40 测试rust的值域安全性 发布于:2023-12-12 09:52 书本的内容 发布于:2023-11-17 17:25 rust代码测试 发布于:2023-11-14 13:41 Learn Rust 发布于:2023-11-09 17:33 Rust学习使用 发布于:2023-05-21 11:21 exercise trait 发布于:2023-04-16 19:42 闭包的捕获 发布于:2023-01-28 16:32 Rust 结构体相关代价 发布于:2022-12-29 09:22 [package] name = "hello_rust" version = "0.1.0" authors = ["gress"] edition = "2018" [dependencies] anyhow= “0.1” 发布于:2022-12-06 20:09 第一个Rust程序 发布于:2022-06-20 00:11 开始学习rust 发布于:2022-05-30 13:51 enum sample 发布于:2022-02-24 15:03 泛型、特性与生命周期协同作战里的实例如何使用 发布于:2022-01-02 16:25 Rust第四章---所有权 发布于:2021-12-31 15:31 Rust第三章-常见编程概念 发布于:2021-12-31 13:16 Hello World Rust 发布于:2021-02-11 19:18 [更多]
显示目录

并发编程



学习嵌入式的绝佳套件,esp8266开源小电视成品,比自己去买开发板+屏幕还要便宜,省去了焊接不当搞坏的风险。 蜂鸣版+触控升级仅36元,更强的硬件、价格全网最低。

点击购买 固件广场

Rust 并发编程

安全高效的处理并发是 Rust 诞生的目的之一,主要解决的是服务器高负载承受能力。

并发(concurrent)的概念是只程序不同的部分独立执行,这与并行(parallel)的概念容易混淆,并行强调的是"同时执行"。

并发往往会造成并行。

本章讲述与并发相关的编程概念和细节。

线程

线程(thread)是一个程序中独立运行的一个部分。

线程不同于进程(process)的地方是线程是程序以内的概念,程序往往是在一个进程中执行的。

在有操作系统的环境中进程往往被交替地调度得以执行,线程则在进程以内由程序进行调度。

由于线程并发很有可能出现并行的情况,所以在并行中可能遇到的死锁、延宕错误常出现于含有并发机制的程序。

为了解决这些问题,很多其它语言(如 Java、C#)采用特殊的运行时(runtime)软件来协调资源,但这样无疑极大地降低了程序的执行效率。

C/C++ 语言在操作系统的最底层也支持多线程,且语言本身以及其编译器不具备侦察和避免并行错误的能力,这对于开发者来说压力很大,开发者需要花费大量的精力避免发生错误。

Rust 不依靠运行时环境,这一点像 C/C++ 一样。

但 Rust 在语言本身就设计了包括所有权机制在内的手段来尽可能地把最常见的错误消灭在编译阶段,这一点其他语言不具备。

但这不意味着我们编程的时候可以不小心,迄今为止由于并发造成的问题还没有在公共范围内得到完全解决,仍有可能出现错误,并发编程时要尽量小心!

Rust 中通过 std::thread::spawn 函数创建新进程:

实例

use std::thread;
use std::time::Duration;

fn spawn_function() {
    for i in 0..5 {
        println!("spawned thread print {}", i);
        thread::sleep(Duration::from_millis(1));
    }
}

fn main() {
    thread::spawn(spawn_function);

    for i in 0..3 {
        println!("main thread print {}", i);
        thread::sleep(Duration::from_millis(1));
    }
}

运行结果:

main thread print 0
spawned thread print 0
main thread print 1
spawned thread print 1
main thread print 2
spawned thread print 2

这个结果在某些情况下顺序有可能变化,但总体上是这样打印出来的。

此程序有一个子线程,目的是打印 5 行文字,主线程打印三行文字,但很显然随着主线程的结束,spawn 线程也随之结束了,并没有完成所有打印。

std::thread::spawn 函数的参数是一个无参函数,但上述写法不是推荐的写法,我们可以使用闭包(closures)来传递函数作为参数:

实例

use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 0..5 {
            println!("spawned thread print {}", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 0..3 {
        println!("main thread print {}", i);
        thread::sleep(Duration::from_millis(1));
    }
}

闭包是可以保存进变量或作为参数传递给其他函数的匿名函数。闭包相当于 Rust 中的 Lambda 表达式,格式如下:

|参数1, 参数2, ...| -> 返回值类型 {
    // 函数体
}

实例

fn main() {
    let inc = |num: i32| -> i32 {
        num + 1
    };
    println!("inc(5) = {}", inc(5));
}

运行结果:

inc(5) = 6

闭包可以省略类型声明使用 Rust 自动类型判断机制:

实例

fn main() {
    let inc = |num| {
        num + 1
    };
    println!("inc(5) = {}", inc(5));
}

结果没有变化。

join 方法

实例

use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 0..5 {
            println!("spawned thread print {}", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 0..3 {
        println!("main thread print {}", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap();
}

运行结果:

main thread print 0 
spawned thread print 0 
spawned thread print 1 
main thread print 1 
spawned thread print 2 
main thread print 2 
spawned thread print 3 
spawned thread print 4

join 方法可以使子线程运行结束后再停止运行程序。


move 强制所有权迁移

这是一个经常遇到的情况:

实例

use std::thread;

fn main() {
    let s = "hello";

    let handle = thread::spawn(|| {
        println!("{}", s);
    });

    handle.join().unwrap();
}

在子线程中尝试使用当前函数的资源,这一定是错误的!因为所有权机制禁止这种危险情况的产生,它将破坏所有权机制销毁资源的一定性。我们可以使用闭包的 move 关键字来处理:

实例

use std::thread;

fn main() {
    let s = "hello";

    let handle = thread::spawn(move || {
        println!("{}", s);
    });

    handle.join().unwrap();
}

消息传递

Rust 中一个实现消息传递并发的主要工具是通道(channel),通道有两部分组成,一个发送者(transmitter)和一个接收者(receiver)。

std::sync::mpsc 包含了消息传递的方法:

实例

use std::thread;
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
    });

    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}

运行结果:

Got: hi

子线程获得了主线程的发送者 tx,并调用了它的 send 方法发送了一个字符串,然后主线程就通过对应的接收者 rx 接收到了。

由JSRUN为你提供的Rust在线运行、在线编译工具
        JSRUN提供的Rust 在线运行,Rust 在线运行工具,基于linux操作系统环境提供线上编译和线上运行,具有运行快速,运行结果与常用开发、生产环境保持一致的特点。
yout