4

我想在 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"
}
4

2 回答 2

5

第一个错误是你写了result == true. 这应该改为result = true

true您应该从 while 条件中删除该值。它没有影响。

BowTest对象中,您应该在g.bow(a)指令之后添加,Thread.sleep(1000)以便给参与者足够的时间来响应消息。

这样,您的代码应该可以工作。但它仍然有一个僵局。如果您将更改g.bow(a)执行a.bow(g)将冻结。这是由receive阻塞引起的。每个参与者都在等待 Bowed 消息,但他们无法响应 BowBack 消息。

当您响应消息时,receive只有在您确定参与者会收到指定消息时才应使用阻止。但通常这不是设计演员的好习惯。他们不应该阻止。Actor 的主要目的是尽可能快地响应消息。如果您必须执行一项大任务,您应该使用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)
      }
    }

于 2010-03-04T12:09:37.207 回答
0

我认为不是死锁,只是一个普通的错误。您的评论下有两行:

received == true

这应该=代替==. 我没有深入研究(这突然出现在我身上),但看起来这可以解决你的问题。

于 2010-03-04T12:09:02.027 回答