斯卡拉的'死锁'

时间:2010-03-04 09:53:54

标签: scala actor

我想在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 个答案:

答案 0 :(得分:5)

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

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

BowTest对象中,您应该在g.bow(a)指令Thread.sleep(1000)之后添加,以便为演员留出足够的时间来回复消息。

这样你的代码就可以了。但它仍然陷入僵局。如果您要更改g.bow(a)中的a.bow(g),执行将会冻结。这是由receive块引起的。每个演员都在等待Bowed消息,但他们无法响应BowBack消息。

当您回复消息时,只有在确定actor将获取指定消息时才应使用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)
      }
    }

答案 1 :(得分:0)

我认为,不是僵局,只是一个普通的错误。评论中有两行:

received == true

这应该是=而不是==。我没有深入研究(这对我来说很突出),但看起来这样可以解决你的问题。