我想在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)
第一个错误是你写的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)
}
}