Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Rust thread runs more than another

Good afternoon everyone, I’m learning rust and I would like to ask a question, in the code below one thread always works more than the other, there doesn’t seem to be a normal distribution of work between the threads.

I wrote the same code in c++ and it works just as well, can someone help me and tell me where I went wrong in rust?

code:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

use std::fmt;
use std::sync::{Arc, Mutex};
use std::thread;
use tokio::time::Duration;
struct Client {
    id: i32,
}
impl fmt::Display for Client {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "Client id: {:?}", self.id)
    }
}
fn main() {
    // ======================
    let client: Client = Client { id: 0 };
    let counter = Arc::new(Mutex::new(client));
    let mut handles = vec![];

    // ======================
    // THREAD 1
    // ======================
    let safe_client_1 = Arc::clone(&counter);
    let thread_1 = thread::spawn(move || loop {
        let mut num = safe_client_1.lock().unwrap();
        num.id += 1;
        print!("thread 1: {}", num);
        thread::sleep(Duration::from_secs(1));
    });
    handles.push(thread_1);

    // ======================
    // THREAD 2
    // ======================
    let safe_client_2 = Arc::clone(&counter);
    let thread_2 = thread::spawn(move || loop {
        let mut num = safe_client_2.lock().unwrap();
        num.id -= 1;
        print!("thread 2: {}", num);
        thread::sleep(Duration::from_secs(1));
    });

    loop {}
}

output:

thread 1: Client id: 1
thread 1: Client id: 2
thread 2: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 2: Client id: -2
thread 2: Client id: -3
thread 2: Client id: -4
thread 2: Client id: -5
thread 2: Client id: -6
thread 2: Client id: -7
thread 1: Client id: -6
thread 2: Client id: -7
thread 2: Client id: -8
thread 2: Client id: -9
thread 2: Client id: -10
thread 2: Client id: -11
thread 2: Client id: -12
thread 2: Client id: -13
thread 2: Client id: -14
thread 2: Client id: -15
thread 2: Client id: -16
thread 2: Client id: -17
thread 2: Client id: -18
thread 2: Client id: -19
thread 2: Client id: -20
thread 2: Client id: -21
thread 2: Client id: -22
thread 2: Client id: -23
thread 2: Client id: -24
thread 2: Client id: -25
thread 2: Client id: -26
thread 2: Client id: -27

Solution code:

use std::fmt;
use std::sync::{Arc, Mutex};
use std::thread;
use tokio::time::Duration;
struct Client {
    id: i32,
}
impl fmt::Display for Client {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "Client id: {:?}", self.id)
    }
}
fn main() {
    // ======================
    let client: Client = Client { id: 0 };
    let counter = Arc::new(Mutex::new(client));

    // ======================
    // THREAD 1
    // ======================
    let safe_client_1 = Arc::clone(&counter);
    let thread_1 = thread::spawn(move || loop {
        let mut num = safe_client_1.lock().unwrap();
        num.id += 1;
        print!("thread 1: {}", num);
        drop(num);
        thread::sleep(Duration::from_secs(1));
    });

    // ======================
    // THREAD 2
    // ======================
    let safe_client_2 = Arc::clone(&counter);
    let thread_2 = thread::spawn(move || loop {
        let mut num = safe_client_2.lock().unwrap();
        num.id -= 1;
        print!("thread 2: {}", num);
        drop(num);

        thread::sleep(Duration::from_secs(1));
    });

    loop {}
}

output:

thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0

>Solution :

You sleep while holding the lock. Do this instead:

let thread_1 = thread::spawn(move || loop {
    let mut num = safe_client_1.lock().unwrap();
    num.id += 1;
    print!("thread 1: {}", num);
    drop(num);
    thread::sleep(Duration::from_secs(1));
});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading