Reputation: 15103
If i have this synchronized code which i want to replace with actors with no synchronization, how?
public synchronized int incrementAndGet() {
i = i + 1;
return i;
}
and i have a bunch of users in web site where i need to return each an incrementing number... how can i replace that code with actors code which have no synchronizations thus have no blocking synchronizing code. which i guess would thenn be able to run it on multicores etc (isn't that the purpose of actors?).
Upvotes: 5
Views: 412
Reputation: 3508
Synchronously incrementing a counter (as in incrementAndGet()
) has very little benefit if you want to use an actor. Hidden from view there is actually synchronization in the mailbox for the actor. Also, the AtomicInteger class works just fine on multicore architectures.
Upvotes: 0
Reputation: 40461
Concurrency is a vast domain with multiple problems and pitfalls. There isn't a single approach able to solve all problems and a real concurrency expert is able to combine several methods to obtain the best result.
Currently on the JVM world, I don't think there are better alternatives than atomic integers for incrementing a counter, especially if the contention is very high.
That being said, if you want to use actors, the trick to get performance and scalability is to avoid ask (?
) operations as much as possible. Use tell instead (!
) and then yield. When the result is available, the actor will receive it and resume control. Nothing blocks and the thread pool is able to take care of the other actors in the mean time. That works only if most of you code is inside actors.
Starting with Thomas solution, you can write something like:
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
}
}
}
Upvotes: 3
Reputation: 340743
A simple actor wrapping i
in its internal state:
case object Inc
class IncrementingActor extends Actor {
var i = 0
protected def receive = {
case Inc =>
i += 1
sender ! i
}
}
And blocking usage (you need to obtain incrementAndGet
somehow):
import akka.pattern.ask
def incrementAndGet() =
Await.result((incrementingActor ? Inc).mapTo[Int], 1 seconds)
This code is: slow, complicated and non-idiomatic. What about AtomicInteger
?
Upvotes: 3