斯卡拉的'死锁'

Xen*_*fex 4 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"
}
Run Code Online (Sandbox Code Playgroud)

Ion*_*anu 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)
      }
    }