Safely Share Mutable Data with Sync and Atomicity in Rust

20 Jul 2023 Balmiki Mandal 0 Rust Programming

Safely Share Mutable Data with Sync and Atomicity in Rust

Rust programming language allows developers to create safe and secure programs, particularly when it comes to sharing data through concurrent processes. When two or more threads are accessing the same data simultaneously, it is important that the process is executed in an atomic manner, while still providing the necessary synchronization to ensure data safety and correctness. Fortunately, Rust provides several tools for safely sharing mutable data between multiple threads with sync and atomicity.

Rust provides two main mechanisms for safely sharing mutable data between threads:

  • Sync: This trait is used to mark types that can be safely shared between threads. A type is Sync if and only if it is Send and &T is Send. This means that the type can be passed between threads without the risk of data races.
  • Atomicity: This refers to the property of an operation that cannot be interrupted by another thread. Atomic operations are used to ensure that the state of a shared variable is not corrupted by concurrent access.

Here are some examples of how to safely share mutable data with Sync and atomicity in Rust:

  • Using Arc<T>: Arc<T> is a smart pointer that is atomically reference counted. This means that it can be safely shared between threads without the risk of data races. For example, the following code safely shares a mutable integer between two threads:
use std::sync::Arc;

fn main() {
    let mut data = Arc::new(5);

    let handle1 = data.clone();
    let handle2 = data.clone();

    thread::spawn(move || {
        *handle1 += 1;
    });

    thread::spawn(move || {
        *handle2 += 1;
    });

    let result = *data;
    assert_eq!(result, 7);
}
  • Using Mutex<T>: Mutex<T> is a synchronization primitive that allows you to lock a shared variable for exclusive access. This can be used to ensure that only one thread can access a variable at a time, which prevents data races. For example, the following code safely shares a mutable integer between two threads using a mutex:
use std::sync::Mutex;

fn main() {
    let mut data = Mutex::new(5);

    let handle1 = data.lock().unwrap();
    let handle2 = data.lock().unwrap();

    *handle1 += 1;
    *handle2 += 1;

    let result = *data.lock().unwrap();
    assert_eq!(result, 7);
}
  • Using atomic types: Rust also provides a number of atomic types that can be used to safely share mutable data between threads. These types are guaranteed to be atomic, which means that their state cannot be corrupted by concurrent access. For example, the following code safely shares a mutable integer between two threads using an atomic type:

 

use std::sync::atomic::AtomicUsize;

fn main() {
    let mut data = AtomicUsize::new(5);

    let handle1 = data.clone();
    let handle2 = data.clone();

    thread::spawn(move || {
        data.fetch_add(1, Ordering::SeqCst);
    });

    thread::spawn(move || {
        data.fetch_add(1, Ordering::SeqCst);
    });

    let result = data.load(Ordering::SeqCst);
    assert_eq!(result, 7);
}

BY: Balmiki Mandal

Related Blogs

Post Comments.

Login to Post a Comment

No comments yet, Be the first to comment.