How We can do Fearless Concurrency in RUST

Handling concurrent programming safely and efficiently is another of Rust’s major goals. Concurrent programming, where different parts of the program execute independently, and parallelly.

Creating Thread-In RUST:-

In RUST to create a new thread, we call the thread:: spawn function and pass it in a closure containing the code we want to run in the new thread.

Example:

Filename: src/main.rs

use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}
Output:
hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!

Implementing Message Passing in RUST using Threads:-

In RUST to achieve concurrency. It uses mpsc (multiple producers and single consumer) channels, functions.channel can have multiple sending ends that produce values but only one receiving end that consumes those values.

Example:

Filename: src/main.rs

use std::thread;
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();

    let t= mpsc::Sender::clone(&tx);;
    thread::spawn(move || {
        let val = String::from("sender 1 says - hello world");
        t.send(val).unwrap();
    });

    thread::spawn(move || {
        let val = String::from("sender 2 says - hello world");
        tx.send(val).unwrap();
    });

    for received in rx {
        println!("Got: {}", received);
    }

}
Output: 
Compiling thread_example v0.1.0 (file:///home/knoldus/Rustprojects/thread_example)                                                                         
    Finished dev [unoptimized + debuginfo] target(s) in 0.97s
     Running `target/debug/thread_example`
Got: sender 1 says - hello world
Got: sender 2 says - hello world

Shared-State Concurrency in RUST Using Threads:-

Message passing is a fine way of handling concurrency, but it’s not the only one. we can also use shared-state. It is a method to achieve concurrency. In which it can to allow accessing data from one thread at a time using mutexes. A mutex is an abbreviation for mutual exclusion as in mutex allows only one thread to access some data at any given time. To access the data in a mutex, a thread must first signal that it wants to access by asking to acquire the mutex’s lock. The lock is a data structure that is part of the mutex that keeps track of who currently has exclusive access to the data. Therefore, the mutex is described as guarding the data it holds via the locking system.

Example:

Filename: src/main.rs

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

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();

            *num += 1;
        });
        handles.push(handle);
    }

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

    println!("Result: {}", *counter.lock().unwrap());
}

Output:
Result: 10

Arc<T> is a type that is safe to use in concurrent situations. The a stands for atomic, meaning it’s automatically reference counted type. You just assume it like a primitive data type.

References:

https://doc.rust-lang.org/book

 

Leave a Reply

%d bloggers like this: