Concurrency 在多个线程之间共享可变的self

Concurrency 在多个线程之间共享可变的self,concurrency,rust,Concurrency,Rust,我有一个服务器,它接受来自多个客户端的连接。每个客户端都可以向服务器发送一条消息,该消息将广播给所有其他客户端。问题是处理每个连接的函数都应该有一个对服务器的引用。但是,我希望在单独的线程中处理连接,因此不能直接使用引用 由于scoped已被弃用,我尝试在Arc中包装self,但随后出现了更多问题。以下是我的尝试: struct Server { listener: TcpListener, clients: Vec<TcpStream> } impl Server

我有一个服务器,它接受来自多个客户端的连接。每个客户端都可以向服务器发送一条消息,该消息将广播给所有其他客户端。问题是处理每个连接的函数都应该有一个对服务器的引用。但是,我希望在单独的线程中处理连接,因此不能直接使用引用

由于
scoped
已被弃用,我尝试在
Arc
中包装
self
,但随后出现了更多问题。以下是我的尝试:

struct Server {
    listener: TcpListener,
    clients: Vec<TcpStream>
}

impl Server {

    fn new() -> Server {
        Server { 
            listener : TcpListener::bind("127.0.0.1:8085").unwrap(),
            clients : vec![] 
        }
    }

    fn handle(&self) {
        println!("test");
    }

    fn start(mut self) {
        let mut handles = vec![];
        let a : Arc<Mutex<Server>> = Arc::new(Mutex::new(self));
        let mut selfm = a.lock().unwrap();

        // cannot borrow as mutable... ?
        for stream in selfm.listener.incoming() {
            match stream {
                Ok(stream) => {
                    selfm.clients.push(stream);
                    let aa = a.clone();
                    handles.push(thread::spawn(move || {
                        aa.lock().unwrap().handle();
                    }));
                },
                Err(e) => { println!("{}", e); },
            }
        }
    }
struct服务器{
听众:TcpListener,
客户:Vec
}
impl服务器{
fn new()->Server{
服务器{
侦听器:TcpListener::bind(“127.0.0.1:8085”).unwrap(),
客户:vec![]
}
}
fn句柄(&self){
println!(“测试”);
}
fn启动(多机自启动){
让mut handles=vec![];
设a:Arc=Arc::new(Mutex::new(self));
让mut selfm=a.lock().unwrap();
//不能作为可变项借用?
对于selfm.listener.incoming()中的流{
匹配流{
Ok(流)=>{
selfm.clients.push(流);
设aa=a.clone();
handles.push(线程::spawn(移动| |){
aa.lock().unwrap().handle();
}));
},
Err(e)=>{println!(“{}”,e);},
}
}
}


我不知道该怎么办了,我担心所有这些锁都会出现死锁。你有什么建议吗?

这个错误与有多个线程几乎无关。问题是,正如编译器所说,
selfm
已经被借用了

for stream in selfm.listener.incoming() {
因此,它不可能在同一行中被可变地借用

selfm.clients.push(stream);
解决此问题的一种方法是在循环之前分解
selfm
,这样借用就不会冲突。然后,您的
start
方法将如下所示:

fn start(mut self) {
    let mut handles = vec![];
    let a : Arc<Mutex<Server>> = Arc::new(Mutex::new(self));
    let mut selfm = a.lock().unwrap();

     // destructure selfm here to get a reference to the listener and a mutable reference to the clients
    let Server { ref listener, ref mut clients} = *selfm;
    for stream in listener.incoming() { // listener can be used here
        match stream {
            Ok(stream) => {
                clients.push(stream); // clients can be mutated here
                let aa = a.clone();
                handles.push(thread::spawn(move || {
                    aa.lock().unwrap().handle();
                }));
            },
            Err(e) => { println!("{}", e); },
        }
    }
}
fn启动(多个自身){
让mut handles=vec![];
设a:Arc=Arc::new(Mutex::new(self));
让mut selfm=a.lock().unwrap();
//在这里对selfm进行分解,以获取对侦听器的引用和对客户端的可变引用
让服务器{ref listener,ref mut clients}=*selfm;
对于侦听器中的流。传入(){//listener可在此处使用
匹配流{
Ok(流)=>{
clients.push(stream);//这里可以对客户端进行变异
设aa=a.clone();
handles.push(线程::spawn(移动| |){
aa.lock().unwrap().handle();
}));
},
Err(e)=>{println!(“{}”,e);},
}
}
}

(也就是说,您担心锁定是对的,因为互斥锁将一直保持锁定状态,直到
selfm
超出范围,即仅当
start
终止时,即永远不会。我建议使用另一种设计,但我并不清楚为什么希望线程访问服务器结构。)

我知道附加版本中的问题与此无关,但我的所有其他尝试也失败了。线程需要访问服务器,因为它们应该告诉服务器向所有其他流广播消息。只有服务器知道该列表。为寻求更好的解决方案,scoped被弃用。Crate横梁提供了一个新的scoped消息阅读API。需要Rust 1.4(即将发布),但它是稳定的。