我想在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"
}
答案 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
这应该是=
而不是==
。我没有深入研究(这对我来说很突出),但看起来这样可以解决你的问题。