Hi there, in my efforts to debug an application, I wanted to lock two mutexes that are in a vector of mutexes, however, the program blocks forever when trying to acquire the second lock
I must have an incorrect understanding how the language works as to why I'm messing up this badly, if anyone can explain why this doesn't work I'd be very thankful
let test_strips = vec![ Arc::new( Mutex::new( vec![0;1] ) ) ; 2];
let lock1 = test_strips[0].lock().unwrap();
println!("Locked 1");
let lock2 = test_strips[1].lock().unwrap();
println!("Locked 2"); //We never reach this
drop(lock1);
drop(lock2);
This is the problem - initalizing a Vec like this creates two clones of the same Arc (which are both referencing the same data), so you're actually locking the same mutex twice. If you create two seperate mutexes and then do vec![mutex1, mutex2], it should work.
The vec![x; n] macro creates many clones of a single element, it doesn’t re-evaluate the expression multiple times. Hence both your Arcs point to the same mutex.
To fix this, initialize it e.g. with
let test_strips: Vec<_> = std::iter::repeat_with(|| Arc::new( Mutex::new( vec![0;1] ))).take(2).collect();
iter::repeat_with(|| …) creates an infinite iterator whose elements are created by evaluating the given closure. The .take(n) method turns it into an iterator of length n. Finally, collect(), collects those n items into a vector.
Following this post (provided nothing changed in the meantime), this is one of two reasonable (yet unfortunately still somewhat verbose) alternative approaches to produce a Vec of n elements generated by some given closure; the other way involves using Vec::resize_with.