5

この同期コードを同期なしのアクターに置き換えたい場合、どうすればよいですか?

public synchronized int incrementAndGet() {
  i = i + 1;
  return i;
}

そして、私はWebサイトに多数のユーザーを抱えており、それぞれに増分番号を返す必要があります...どうすればそのコードを、同期を持たないアクターコードに置き換えて、ブロック同期コードを持たないことができますか. マルチコアなどで実行できると思います(それがアクターの目的ではありませんか?)。

4

3 に答える 3

3

i内部状態でラップする単純なアクター:

case object Inc

class IncrementingActor extends Actor {
    var i = 0

    protected def receive = {
        case Inc =>
            i += 1
            sender ! i
    }
}

incrementAndGetそして使用をブロックします(何らかの方法で取得する必要があります):

import akka.pattern.ask

def incrementAndGet() = 
  Await.result((incrementingActor ? Inc).mapTo[Int], 1 seconds)

このコードは: 遅く、複雑で、慣用的ではありません。どうAtomicIntegerですか?

于 2012-04-13T18:27:08.923 に答える
3

並行性は、複数の問題と落とし穴を伴う広大な領域です。すべての問題を解決できる単一のアプローチはありません。真の並行処理の専門家は、複数の方法を組み合わせて最良の結果を得ることができます。

現在、JVM の世界では、特に競合が非常に激しい場合、カウンターをインクリメントするためのアトミック整数よりも優れた代替手段はないと思います。

そうは言っても、アクターを使用する場合、パフォーマンスとスケーラビリティーを得るための秘訣は、ask ( ?) 操作をできるだけ避けることです。代わりにtell ( ) を使用して!から、yield を使用します。結果が利用可能になると、アクターはそれを受け取り、制御を再開します。何もブロックされず、その間、スレッド プールは他のアクターを処理できます。これは、ほとんどのコードがアクター内にある場合にのみ機能します。

Thomas ソリューションから始めて、次のように記述できます。

case object Inc
case class Count(i)

class IncrementingActor extends Actor {
   var i = 0
   protected def receive = {
     case Inc =>
        i += 1
        sender ! Count(i)
  }
}

class FooActor( counter: ActorRef ) extends Actor {
  protected def receive = {
    case DoSomething() => {
      // Perform some work
      counter ! Inc
    }
    case Count(i) => {
      // Do something with the counter result   
    }
  }
}
于 2012-04-14T12:01:02.310 に答える
0

アクターを使用する場合、カウンターを同期的にインクリメントしても ( のようにincrementAndGet()) メリットはほとんどありません。ビューからは隠されていますが、実際にはアクターのメールボックスで同期が行われています。また、AtomicIntegerクラスはマルチコア アーキテクチャでも問題なく動作します。

于 2012-04-28T00:27:49.563 に答える