2010-03-04 78 views
4

我想在scala中重寫Sun的關於java中的併發性教程的例子。原始代碼在這裏:http://java.sun.com/docs/books/tutorial/essential/concurrency/deadlock.htmlscala中的'死鎖'

此代碼是不正確的。它凍結了評論所指的地方。任何人都可以糾正這個?提前致謝。

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

是否可以將代碼量減少到再現死鎖所需的絕對最小值? – Andrey 2010-03-04 11:25:21

回答

5

第一個錯誤是你寫的result == true。這應該更改爲result = true

您應該刪除while條件中的true值。它沒有影響。

BowTest對象中,您應該在g.bow(a)指令Thread.sleep(1000)後面添加以給參與者足夠的時間來響應消息。

這樣你的代碼應該可以工作。但它仍然陷入僵局。如果您將更改g.bow(a)a.bow(g)執行將凍結。這是由receive塊造成的。每個演員都在等待Bowed消息,但他們無法回覆BowBack消息。

當您回覆消息時,只有在確定演員將獲得指定消息時,才應使用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) 
     } 
    } 
 
+0

那你肯定比我的回答做得更多了! – Calum 2010-03-04 12:53:28

+0

非常感謝。這確實是一個解決方案。粘貼在這裏的代碼有點混亂,因爲我正在調整它。 – Xenofex 2010-03-04 14:58:31

+0

要完全模擬這種交互似乎會導致更復雜的模型。 – Xenofex 2010-03-05 01:52:52

0

沒有死鎖,只是一個普通的ol錯誤,我想。兩行您的評論下:

received == true

這應該是=而不是==。我沒有深入探討(這突然出現在我身上),但它看起來像這樣會解決您的問題。