multithreading - Rust:使用互斥体允许从多个线程访问数据

标签 multithreading rust mutex atomic

我正在尝试创建对当前 TCP 连接的引用。在此代码中,我尝试在循环中打印当前 TCP 连接的对等地址并休眠 10 秒,我遇到的错误是访问多个线程之间的数据。

我希望能够在任何给定时间点从不同的线程操作 TCPStream,以执行诸如关闭 TCPStream 或获取对等地址之类的操作。

您能否让我知道我做错了什么,以便我可以更好地了解 Arc 和 Mutex 的工作原理?

use std::io::Read;
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

fn main() {
    let server = Server {
        connected_clients: Arc::new(Mutex::new(Vec::new()))
    };

    thread::spawn(move || {
        let listener = TcpListener::bind("127.0.0.1:25565").unwrap();

        // For each new connection start a new thread
        for stream in listener.incoming() {
            let stream = Arc::new(Mutex::new(stream.unwrap()));
            let client = Client {
                stream: stream.clone()
            };

            let cc = server.connected_clients.clone();
            cc.lock().unwrap().push(client);

            thread::spawn(move || {

                // TODO: Add client to the connected_clients Vec
                let mut buffer = [0; 1024];
                loop {
                    stream.lock().unwrap().read(&mut buffer).unwrap();
                    println!("{}", String::from_utf8(Vec::from(&buffer[..])).unwrap().trim_end_matches(char::from(0)));
                }
            });
        }
    });

    loop {
        thread::sleep(Duration::from_secs(10));
        // let vec = server.lock().unwrap().connected_clients.lock().unwrap().iter();
        for client in server.connected_clients.lock().unwrap().iter() {
            println!("{:?}", client.stream.lock().unwrap().peer_addr().unwrap())
        }

    }
}

#[derive(Debug)]
struct Server {
    connected_clients: Arc<Mutex<Vec<Client>>>,
}

#[derive(Debug)]
struct Client {
    stream: Arc<Mutex<TcpStream>>
}

错误:

error[E0382]: borrow of moved value: `server.connected_clients`                          
    --> src\main.rs:40:23                                                                
     |                                                                                   
12   |     thread::spawn(move || {                                                       
     |                   ------- value moved into closure here                           
...                                                                                      
22   |             let cc = server.connected_clients.clone();                            
     |                      ------------------------ variable moved due to use in closure
...                                                                                      
40   |         for client in server.connected_clients.lock().unwrap().iter() {
     |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
     |
     = note: move occurs because `server.connected_clients` has type `Arc<Mutex<Vec<Client>>>`, which does not implement the `Copy` trait
     = note: borrow occurs due to deref coercion to `Mutex<Vec<Client>>`

最佳答案

只需移动该行 let cc = server.connected_clients.clone();第一行之前 thread::spawn(move || { .

move闭包的关键字现在将取得 cc 的所有权,那么原来的server.connected_clients将在程序结束时保持可用于循环。

背后的想法Rc::clone()Arc::clone()正是为了move的目的闭包:我们不是将指向资源的原始引用计数指针移动到闭包中,而是将其克隆移动,并且指向资源的原始引用计数指针在其原始上下文中仍然可用。

关于multithreading - Rust:使用互斥体允许从多个线程访问数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73392374/

相关文章:

rust - 如何删除我无权在 Rust 中访问的目录?

linux - 什么是非阻塞信号量?

c - 如何确保在销毁互斥体之前没有其他线程立即获取锁

rust - Rust 中 'mut' 关键字的用法

android - 我一次可以观察多少个 Stateflow?

c - 当只有一个线程写入共享变量时,我需要锁吗?

java - 不同(不相同)的副本集是从单例对象返回的

rust - 在 Rust 中别名闭包类型,但编译器要求生命周期说明符

c++ - QMutexLocker 和 QMutex 哪个更好用?

java - notify/notifyall 是否释放被持有的锁