Absolutely unsafe multithreading in rust

I want to implement parallel data modification in Rust with absolutely zero locks, just as it could be implemented in C or C++.

Consider this example of a completely safe and normal program:

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

fn main() {
    let data: Arc<Mutex<Vec<i32>>> = Arc::new(Mutex::new(vec![]));

    let mut handles = vec![];

    for i in 0..16 {
        let data = Arc::clone(&data);
        let handle = thread::spawn(move || {
            let mut mut_data = data.lock().unwrap();
            (*mut_data).push(i);
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("DATA AFTER MODIFICATION: {:?}", data.lock().unwrap());
}

Is there any way to make it not use Arc and Mutex (since both have an implicit lock)?
I hope to use some unsafe blocks and raw pointers to implement this, but I haven't found a way to avoid compiler errors yet, so it would be great if someone could help me with this.

While one could probably write similar code in C or C++ with out mutex pr other protection and get it to compile without error it would almost certainly be failure prone at run time. Do you really want that in your Rust program?

What do you want to do in order to facilitate calling Vec::push from multiple threads without locking and henceforth causing immediate UB? Or is this just an example? In that case, it would be important to know what you want to do realistically as there might be lock-free algorithms/data structures you could use instead of Vec. lockfree::stack::Stack comes to mind, for example.

1 Like

Removing the lock from your example would be incorrect because push can reallocate the vector.

Anyway, let's say that you're using indexes instead of push and that you make sure to not touch the same index from several threads. Then you can probably do it with the rayon crate, but if you must use unsafe, then check out this SO answer.

3 Likes

Is something like this what you're looking for?

use std::thread;

fn main() {
    let mut data = [0;16];
    thread::scope(|scope| {
        for (i,slot) in data.iter_mut().enumerate() {
            scope.spawn(move || { *slot = i; });
        }
    });

    println!("DATA AFTER MODIFICATION: {:?}", data);
}
2 Likes