I want to rewrite in scala the example from Sun’s tutorial about concurrency in java. The original code is here: http://java.sun.com/docs/books/tutorial/essential/concurrency/deadlock.html
This code is incorrect. It freezes at where the comment indicates. Could anyone correct this? Thanks in advance.
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"
}
The first mistake is that you wrote
result == true. This should be changed toresult = trueYou should delete the
truevalue from the while condition. It has no influence.In the
BowTestobject you should add after theg.bow(a)instructionThread.sleep(1000)to give actors enough time to respond to the messages.In this way your code should work. But still it has a deadlock. If you will change
g.bow(a)ina.bow(g)the execution will freeze. This is caused by thereceiveblock. Each actor is waiting for the Bowed message, but they cannot respond to the BowBack message.When you are responding to a message, you should use
receiveblock only if you are sure that the actor will get the specified messages. But usually this is not a good practice in designing actors. They should not block. The main purpose of an actor is to respond as fast as possible to a message. If you have to do a big task you should usefutures, but in this case is not required.A solution will be to retain the persons which are bowed in a list. When the actor have to bow a person it adds it in the list. When the actor is bowed by a person which is in the list, it removes that person from the list.