Multithreading 如何防止自动执行同步

Multithreading 如何防止自动执行同步,multithreading,struct,rust,traits,unsafe,Multithreading,Struct,Rust,Traits,Unsafe,我有一个包含以下方法的不安全代码的结构: use std::sync::Arc; use std::thread; #[derive(Debug)] struct Foo<T> { items: Vec<Box<(T, String)>>, } impl<T> Foo<T> { pub fn add_element(&self, element: T, key: String) { if !(

我有一个包含以下方法的不安全代码的结构:

use std::sync::Arc;
use std::thread;

#[derive(Debug)]
struct Foo<T> {
    items: Vec<Box<(T, String)>>,
}

impl<T> Foo<T> {
    pub fn add_element(&self, element: T, key: String) {
        if !(self.items.iter().any( |i| i.1 == key)) {
            let mut items = unsafe {change_mut(&(self.items))};
            items.push(Box::new((element,key)));
        }
    }
}

unsafe fn change_mut<T>(x: &T) -> &mut T { // changes &self to &mut self
    &mut *(x as *const T as *mut T)
}

fn main() {
    let foo = Arc::new(Foo { items: vec!() });
    let clone = foo.clone();

    // This should not be possible, as it might lead to UB
    thread::spawn(move || clone.add_element(1, String::from("one")));

    println!("{:?}", *foo);

}

Rust中的内部易变性要求使用1作为一个提示,提示编译器正常规则不适用

因此,您的结构应如下所示:

#[derive(Debug)]
struct Foo<T> {
    items: UnsafeCell<Vec<Box<(T, String)>>>,
}
使用
UnsafeCell
使得
change\u mut
完全没有必要:毕竟,
UnsafeCell
的目的是允许内部可变性。请注意它的
get
方法如何返回原始指针,如果没有
不安全的
块,就无法取消引用该指针


由于
UnsafeCell
没有实现
Sync
Foo
也不会实现
Sync
,因此没有必要使用否定实现或任何标记



1如果您不直接使用它,那么您使用的抽象很可能是建立在它之上的。它尽可能的特殊:它是一个lang项目,由其属性
#[lang=“unsafe_cell”]

表示。请尝试提供一个链接,理想情况下作为到操场的链接。如果不必猜测省略了什么,那么测试解决方案的正确性就容易多了。(MCVE的示例:)不,即使使用单个线程,代码也不是完全安全的。将an&T转换为a&mut T是非常困难的。您应该为此使用UnsafeCell,这也可以解决您的同步问题。@BurntSushi5您可能需要加入:-)
#[derive(Debug)]
struct Foo<T> {
    items: UnsafeCell<Vec<Box<(T, String)>>>,
}
impl<T> Foo<T> {
    pub fn add_element(&self, element: T, key: String) {
        if !(self.items.iter().any( |i| i.1 == key)) {
            let mut items = unsafe { &mut *self.items.get() };
            //                       ^~~~~~~~~~~~~~~~~~~~~~
            items.push(Box::new((element,key)));
        }
    }
}