尝试学习和理解线程执行中不安全 Rust 的行为。有人可以解释我在这里可能做错了什么吗?

-1 multithreading unsafe vector rust raw-pointer

use std::sync::Arc;
use std::sync::atomic::{AtomicPtr, Ordering};
use std::thread;

fn main() {

    let mut arr = vec![1,2,3];
    let ptr = &mut arr as *mut Vec<i32>;
    println!("ptr : {:?}",ptr);
    // unsafe { (*ptr)[0] = 2; }
    let ptr_ref_1 = Arc::new(AtomicPtr::new(ptr));
    let a = thread::spawn(move || unsafe {
        let ptr_inner = (ptr_ref_1).load(Ordering::SeqCst);
        println!("ptr_inner_1 {:?}",ptr_inner);
        (*ptr_inner).push(4);
        println!("4 is done");
    });
    let ptr_ref_2 = Arc::new(AtomicPtr::new(ptr));
    let b = thread::spawn(move || unsafe {
        let ptr_inner = (ptr_ref_2).load(Ordering::SeqCst);
        println!("ptr_inner_2 {:?}",ptr_inner);

        (*ptr_inner).push(5);
        println!("5 is done");
    });
    let ptr_ref_3 = Arc::new(AtomicPtr::new(ptr));
    let c = thread::spawn(move || unsafe {
        // Read value
        // println!("{:?}",*(ptr_ref_3.load(Ordering::SeqCst)));
        let ptr_inner = (ptr_ref_3).load(Ordering::SeqCst);
        println!("ptr_inner_3 {:?}",ptr_inner);

        (*ptr_inner).push(6);
        println!("6 is done");
    });
    a.join().unwrap();
    b.join().unwrap();
    c.join().unwrap();
    println!("final values {:?}",arr);
}

Run Code Online (Sandbox Code Playgroud)

95% 的运行正常,5% 的运行抛出以下错误

Output : 

ptr : 0x16d65f008
ptr_inner_1 0x16d65f008
ptr_inner_2 0x16d65f008
5 is done
main(75339,0x16d867000) malloc: pointer 0x6000022a8010 being reallocated was not allocated
main(75339,0x16d867000) malloc: *** set a breakpoint in malloc_error_break to debug
Signal: SIGABRT (signal SIGABRT)
Run Code Online (Sandbox Code Playgroud)

尝试使用不安全的 Rust 和线程来改变对向量的单个指针的多个引用。我了解如何使用 Arc/Mutex 来更新多个线程中的值,但不确定这里的不安全生锈错误是什么。

dre*_*ato 6

这是一个简单的数据竞争,因为您试图Vec在没有任何同步的情况下改变三个不同线程中的一个。事实上,您正在使用的东西AtomicPtr在这里什么也没做。通常,当您使用 时AtomicPtr<T>,需要将其替换为另一个T指针或空指针,修改原始的T,然后将其放回去。

此代码始终是未定义的行为,但实际崩溃的 5% 可能是因为Vec在一个线程中重新分配,而另一个线程正在尝试写入它。

这段代码可能最好用通道来编写。