MST

星途 面试题库

面试题:Rust互斥锁与死锁场景分析

考虑以下代码片段: ```rust use std::sync::{Arc, Mutex}; use std::thread; let data1 = Arc::new(Mutex::new(0)); let data2 = Arc::new(Mutex::new(1)); let handle1 = thread::spawn(move || { let lock1 = data1.lock().unwrap(); let lock2 = data2.lock().unwrap(); // 进行一些操作 }); let handle2 = thread::spawn(move || { let lock2 = data2.lock().unwrap(); let lock1 = data1.lock().unwrap(); // 进行一些操作 }); handle1.join().unwrap(); handle2.join().unwrap(); ``` 这段代码会导致死锁吗?请解释原因,并提出至少一种避免死锁的方法。
12.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 是否会导致死锁
    • 这段代码会导致死锁。
    • 原因是handle1线程首先获取data1的锁,然后尝试获取data2的锁;而handle2线程首先获取data2的锁,然后尝试获取data1的锁。如果handle1获取了data1的锁,同时handle2获取了data2的锁,那么两个线程都会阻塞等待对方释放锁,从而形成死锁。
  2. 避免死锁的方法
    • 方法一:固定锁获取顺序
      • 确保所有线程以相同的顺序获取锁。例如,两个线程都先获取data1的锁,再获取data2的锁。
      use std::sync::{Arc, Mutex};
      use std::thread;
      
      let data1 = Arc::new(Mutex::new(0));
      let data2 = Arc::new(Mutex::new(1));
      
      let handle1 = thread::spawn(move || {
          let lock1 = data1.lock().unwrap();
          let lock2 = data2.lock().unwrap();
          // 进行一些操作
      });
      
      let handle2 = thread::spawn(move || {
          let lock1 = data1.lock().unwrap();
          let lock2 = data2.lock().unwrap();
          // 进行一些操作
      });
      
      handle1.join().unwrap();
      handle2.join().unwrap();
      
    • 方法二:使用try_lock
      • 使用try_lock方法尝试获取锁,如果获取失败则释放已获取的锁并进行重试或采取其他策略。
      use std::sync::{Arc, Mutex};
      use std::thread;
      
      let data1 = Arc::new(Mutex::new(0));
      let data2 = Arc::new(Mutex::new(1));
      
      let handle1 = thread::spawn(move || {
          loop {
              let lock1 = match data1.try_lock() {
                  Ok(lock) => lock,
                  Err(_) => {
                      std::thread::yield_now();
                      continue;
                  }
              };
              let lock2 = match data2.try_lock() {
                  Ok(lock) => lock,
                  Err(_) => {
                      drop(lock1);
                      std::thread::yield_now();
                      continue;
                  }
              };
              // 进行一些操作
              break;
          }
      });
      
      let handle2 = thread::spawn(move || {
          loop {
              let lock1 = match data1.try_lock() {
                  Ok(lock) => lock,
                  Err(_) => {
                      std::thread::yield_now();
                      continue;
                  }
              };
              let lock2 = match data2.try_lock() {
                  Ok(lock) => lock,
                  Err(_) => {
                      drop(lock1);
                      std::thread::yield_now();
                      continue;
                  }
              };
              // 进行一些操作
              break;
          }
      });
      
      handle1.join().unwrap();
      handle2.join().unwrap();