'Тупик' в скале - PullRequest
       9

'Тупик' в скале

4 голосов
/ 04 марта 2010

Я хочу переписать в scala пример из руководства Sun о параллелизме в java.Оригинальный код здесь: http://java.sun.com/docs/books/tutorial/essential/concurrency/deadlock.html

Этот код неверен.Он останавливается там, где указывает комментарий.Может ли кто-нибудь исправить это?Заранее спасибо.

import scala.actors.Actor

class Person(val name: String) extends Actor {

  def bow(other: Person) {
    other ! Bow(this)
  }

  private def bowBack(backTo: Person) {
    println(this.name + " is bowing back to " + backTo.name)
    backTo ! Bowed(this)
  }

  def act() {
    while (true) {
      receive {
        case Bow(p) =>
          println(this.name + " is bowing to " + p.name)
          p ! BowBack(this)
          println("    wating for bowing back...")
          var received = false
          while (true && received == false) {
            receive {    //blocked here
              case Bowed(other) if p == other =>
                println(" ... " + this.name + " has bowed to " + other.name)
            received == true
            }
          }
          println(this.name + " has bowed to " + p.name)
        case BowBack(p) =>
          println(this.name + " is bowing back to " + p.name)
          p ! Bowed(this)
        case "EXIT" => return
        case x => println(x)
      }
    }
  }
}

abstract case class Action()
case class Bow(person: Person) extends Action
case class BowBack(person: Person) extends Action
case class Bowed(person: Person) extends Action

object BowTest extends Application {
  val a = new Person("Alphone")
  val g = new Person("Gaston")
  a.start()
  g.start()

  a ! Bow(g)
  //g.bow(a)

  a ! "EXIT"
  g ! "EXIT"
}

Ответы [ 2 ]

5 голосов
/ 04 марта 2010

Первая ошибка в том, что вы написали result == true. Это должно быть изменено на result = true

Вы должны удалить значение true из условия while. Это не имеет никакого влияния.

В объекте BowTest вы должны добавить после инструкции g.bow(a) Thread.sleep(1000), чтобы дать актерам достаточно времени для ответа на сообщения.

Таким образом, ваш код должен работать. Но все же у него есть тупик. Если вы измените g.bow(a) на a.bow(g), выполнение будет остановлено. Это вызвано блоком receive. Каждый актер ожидает сообщения Bowed, но он не может ответить на сообщение BowBack.

Когда вы отвечаете на сообщение, вы должны использовать блок receive, только если вы уверены, что субъект получит указанные сообщения. Но обычно это не очень хорошая практика в проектировании актеров. Они не должны блокировать. Основная цель актера - максимально быстро ответить на сообщение. Если вам нужно выполнить большую задачу, вы должны использовать futures, но в этом случае это не требуется.

Решение будет заключаться в том, чтобы сохранить людей, которые склонены в списке. Когда актер должен поклониться человеку, он добавляет его в список. Когда актер поклоняется человеку, который находится в списке, он удаляет этого человека из списка.


    while (true) {
      react {
        case Bow(p) =>
          println(this.name + " is bowing to " + p.name)
          addPersonToBowList(p)
          p ! BowBack(this)

        case Bowed(other) if isPersonInBowList(other) =>
                println(" ... " + this.name + " has bowed to " + other.name)
                removePersonFromBowList(other)
        case BowBack(p) =>
          println(this.name + " is bowing back to " + p.name)
          p ! Bowed(this)
        case "EXIT" => exit()
        case x => println(x)
      }
    }

0 голосов
/ 04 марта 2010

Не тупик, просто ошибка, я думаю. Две строки под вашим комментарием:

received == true

Это должно быть = вместо ==. Я не посмотрел вглубь (это возникло у меня), но выглядит , как будто это решило бы вашу проблему.

...