How to have shared mutable state without lock


#1

I have a struct (say Demo), struct demo is a lock free data structure. I would like to create one instance of it and then send it to two threads. The two threads must be able to mutate the instance of Demo without locking. How do I achieve this?


#2

Is this what you are looking for?

use std::sync::Arc;
use std::cell::UnsafeCell;
use std::thread;

struct Data {
    val1 : u32,
    val2 : u32
}

struct Test {
    data : UnsafeCell<Data>
}
unsafe impl Sync for Test { }

fn main() {
    let data = Arc::new(Test {
        data : UnsafeCell::new(Data {
            val1 : 5,
            val2 : 10
        })
    });
    
    let data1 = data.clone();
    let thread1 = thread::spawn(move || {
        unsafe { (*data1.data.get()).val1 += 15; }
    });
    
    let data2 = data.clone();
    let thread2 = thread::spawn(move || {
        unsafe { (*data2.data.get()).val2 += 5; }
    });
    
    thread1.join();
    thread2.join();

    unsafe {
        println!("Val1: {}", (*data.data.get()).val1);
        println!("Val2: {}", (*data.data.get()).val2);
    }        
}

It is using Arc to share the object across the threads, so I guess there is locking in there. But both threads are able to modify the internal elements without locks.


Data races = undefined behavior?
#3

@pixel It worked, thank you very much .


#4

Arc does not lock. It uses an AtomicUsize (IIRC) to maintain the refcount. This type allows lockless atomic updates with specified ordering requirements.