На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Неправильные Rust-философы , тестовая программа работает не так как ожидалось
    Приветствую!

    Решил скомпилировать тестовую программу "Обедающие философы" на языке Rust из мануала:

    ExpandedWrap disabled
      use std::thread;
      use std::time::Duration;
      use std::sync::{Mutex, Arc};
       
      struct Philosopher {
          name: String,
          left: usize,
          right: usize,
      }
       
      impl Philosopher {
          fn new(name: &str, left: usize, right: usize) -> Philosopher {
              Philosopher {
                  name: name.to_string(),
                  left: left,
                  right: right,
              }
          }
       
          fn eat(&self, table: &Table) {
              let _left = table.forks[self.left].lock().unwrap();
              thread::sleep(Duration::from_millis(150));
              let _right = table.forks[self.right].lock().unwrap();
              println!("{} начала есть.", self.name);
              thread::sleep(Duration::from_millis(1000));
              println!("{} закончила есть.", self.name);
          }
      }
       
      struct Table {
          forks: Vec<Mutex<()>>,
      }
       
      fn main() {
          let table = Arc::new(Table { forks: vec![
              Mutex::new(()),
              Mutex::new(()),
              Mutex::new(()),
              Mutex::new(()),
              Mutex::new(()),
          ]});
       
          let philosophers = vec![
              Philosopher::new("Джудит Батлер", 0, 1),
              Philosopher::new("Рая Дунаевская", 1, 2),
              Philosopher::new("Зарубина Наталья", 2, 3),
              Philosopher::new("Эмма Гольдман", 3, 4),
              Philosopher::new("Анна Шмидт", 0, 4),
          ];
       
          let handles: Vec<_> = philosophers.into_iter().map(|p| {
              let table = table.clone();
              thread::spawn(move || {
                  p.eat(&table);
              })
          }).collect();
          
          for h in handles {
              h.join().unwrap();
          }
      }


    Компилятор версии 1.25 под FreeBSD из портов. Все компилируется и запускается.
    Одна проблема - "философы" едят последовательно, а должны асинхронно.

    Что я делаю не так?

    Добавлено
    ЗЫ: Более того, этот же пример на https://play.rust-lang.org также работает неправильно.
      Убрал первую задержку в 150мс, "философы" начали обедать "правильно". Хм ... :-?
        Вощем, на сколько я понял, реализация была сделана несколько топорно, а именно:

        1) Времена "взятия вилок", "время еды" были константами - такого не бывает
        2) Освобождение ресурса "вилка" предусмотрено не было

        По-сему, если бы последний философ "не был бы левшой", процесс бы вообще в большинстве случаев ловил бы дедлок.
        Ради интереса и обучения - постараюсь переделать.
          Цитата JoeUser @
          2) Освобождение ресурса "вилка" предусмотрено не было

          Тут RAII используется. mutex.lock().unwrap() выдаёт нечто, что ты можешь использовать как объект, защищаемый мьютексом и что в drop-e (это полный аналог плюсовых деструкторов) вызовет unlock.
          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script execution time: 0,0195 ]   [ 15 queries used ]   [ Generated: 28.03.24, 17:45 GMT ]