centos

CentOS上Rust的并发编程实践

小樊
38
2025-09-28 10:36:17
栏目: 编程语言

Installing Rust on CentOS
To start concurrent programming in Rust on CentOS, first install Rust using rustup, the official Rust toolchain installer. Run the following command in your terminal:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

After installation, reload your shell environment to add Rust to your PATH:

source $HOME/.cargo/env

Verify the installation with rustc --version and cargo --version.

Creating a New Rust Project
Use Cargo (Rust’s package manager and build tool) to create a new project for concurrent programming:

cargo new concurrency_demo
cd concurrency_demo

This generates a basic project structure with a src/main.rs file and a Cargo.toml manifest.

1. Thread-Based Concurrency
Rust’s standard library provides the std::thread module for creating and managing threads. The thread::spawn function creates a new thread that executes the provided closure. Use join() to wait for the thread to finish.
Example:

use std::thread;

fn main() {
    let handle = thread::spawn(|| {
        println!("Hello from a spawned thread!");
    });
    println!("Hello from the main thread!");
    handle.join().unwrap(); // Blocks until the thread completes
}

This demonstrates basic thread creation and synchronization.

2. Message Passing with Channels
Rust encourages message passing over shared state to avoid data races. The std::sync::mpsc (Multiple Producer, Single Consumer) module provides channels for thread-safe communication.
Example:

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

fn main() {
    let (tx, rx) = mpsc::channel(); // Create a channel (tx: transmitter, rx: receiver)
    thread::spawn(move || {
        let val = String::from("Message from thread");
        tx.send(val).unwrap(); // Send data to the main thread
    });
    let received = rx.recv().unwrap(); // Receive data (blocks until a message arrives)
    println!("Received: {}", received);
}

Channels ensure safe communication between threads without explicit locking.

3. Shared State with Arc and Mutex
For cases where shared state is unavoidable, use Arc (Atomic Reference Counting) for thread-safe reference counting and Mutex (Mutual Exclusion) to protect data from concurrent access.
Example:

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

fn main() {
    let counter = Arc::new(Mutex::new(0)); // Wrap the counter in Arc and Mutex
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter); // Clone the Arc for each thread
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap(); // Acquire the mutex lock
            *num += 1; // Modify the shared data
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap(); // Wait for all threads to finish
    }

    println!("Final counter value: {}", *counter.lock().unwrap());
}

Arc ensures the counter is safely shared across threads, while Mutex prevents simultaneous modifications.

4. Asynchronous Programming with Tokio
For high-performance I/O-bound tasks (e.g., network servers), use Rust’s async/await syntax with an asynchronous runtime like tokio. Add tokio to your Cargo.toml:

[dependencies]
tokio = { version = "1", features = ["full"] }

Example: A simple TCP echo server that spawns a new task for each client connection:

use tokio::net::TcpListener;
use tokio::prelude::*;

#[tokio::main] // Macro to set up the Tokio runtime
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?; // Bind to localhost:8080
    println!("Server listening on port 8080");

    loop {
        let (mut socket, addr) = listener.accept().await?; // Accept a new connection
        println!("New connection from {:?}", addr);

        // Spawn a new async task to handle the client
        tokio::spawn(async move {
            let mut buf = [0; 1024]; // Buffer for reading data

            loop {
                match socket.read(&mut buf).await { // Read data from the socket
                    Ok(n) if n == 0 => return, // Connection closed by client
                    Ok(n) => {
                        if socket.write_all(&buf[0..n]).await.is_err() { // Echo data back
                            eprintln!("Failed to write to socket");
                            return;
                        }
                    }
                    Err(e) => {
                        eprintln!("Failed to read from socket: {:?}", e);
                        return;
                    }
                }
            }
        });
    }
}

This example uses tokio::spawn to handle each client connection concurrently, enabling efficient handling of multiple clients.

Key Notes for Concurrent Programming in Rust

By leveraging these tools and following Rust’s safety guarantees, you can build efficient and reliable concurrent applications on CentOS.

0
看了该问题的人还看了