Deadlock: Is it a bug, or is it intentional?

I have made this code:

#![allow(unused_must_use)]

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

fn main() {
    
    let v = Arc::new(Mutex::new(vec![1, 2]));
    let u = v.clone();
    
    let th = thread::spawn(move || {
        let mut vector = u.lock().unwrap();
        
        vector.push(4);
    });
    
    let mut vector = v.lock().unwrap();
    vector.push(5);
    
    th.join();
    
    println!("{}, {:?}", vector.len(), *vector );
}

And it compiles fine, but when I try to run the program, I get a "timeout triggered!" message.

Just to recapitulate, Rust aims to avoid thread-unsafety, deadlocks and so on. Almost all the cases that a code seems to break the Rust's rules, it doesn't compile. Then, I thought that avoiding deadlocks and thread-safety were rules and it doesn't compile when I break them.

In this case, it seems to be a deadlock, because of let mut vector = v.lock().unwrap(); before the th.join(). So, my question is: what is this supposed to be? A thing that the compiler still doesn't capture and interpret it as a bug, or is this intentional?

Rust does not aim to avoid deadlocks or "thread-unsafety", it aims to avoid memory unsafety. The thread related part of this is that rust prevents data races. However, logical races and deadlocks are still possible.

As a matter of fact, preventing deadlocks with 100% certainty is impossible without making the language unusable. Basically, you'd need to be able to prove convergence so you couldn't write the following because you couldn't prove that the loop ever terminates (the halting problem):

while some_non_trivial_condition() {
    // do something
}
5 Likes

Guaranteeing no deadlocks is not exactly possible. Rust merely strives to minimize deadlocks, but it doesn't eliminate them completely. It does however guarantee that deadlocks cannot lead to unsafety in safe code.

1 Like

Rust offers channels, and you can use it to write concurrency code without using locks.

3 Likes

It is, just not in a Turing complete language. See Coq.

1 Like

Well, I encapsulated the locking in a scope, so that there's no more deadlock: Rust Playground