如果我有这个同步代码,我想用没有同步的演员替换,怎么做?
public synchronized int incrementAndGet() {
i = i + 1;
return i;
}
我在网站上有一堆用户,我需要向每个用户返回一个递增的数字......我怎样才能用没有同步的Actor代码替换该代码,因此没有阻塞同步代码。我想这将能够在多核等上运行它(这不是演员的目的吗?
一个简单的参与者,将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
呢?
并发是一个具有多个问题和陷阱的庞大领域。没有一种方法能够解决所有问题,真正的并发专家能够组合多种方法来获得最佳结果。
目前在 JVM 世界中,我认为没有比原子整数更好的替代方案来增加计数器,尤其是在争用非常高的情况下。
话虽如此,如果你想使用Actor,获得性能和可伸缩性的诀窍是尽可能避免询问(?
)操作。改用告诉(!
),然后屈服。当结果可用时,参与者将收到它并恢复控制。没有阻塞,线程池能够同时照顾其他参与者。只有当大多数代码都在Actor内部时,这才有效。
从托马斯解决方案开始,你可以写这样的东西:
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
}
}
}
使用Actor,同步递增计数器(如incrementAndGet()
)几乎没有什么好处。隐藏在视图中,实际上在执行组件的邮箱中存在同步。此外,AtomicInteger 类在多核体系结构上工作得很好。