Actors模型专题

Akka的软件事务内存 (STM)

  Actors模型是基于独立程序的前提下,可以隔离更新状态,状态更新只能只能通过消息传递实现。Actors内部保持住状态,异步消息传递意味着没有可以提供给组件一致性的调用过程。对于交易系统,如银行账户存款和提款的操作过程是需要是原子的,这可能需要跨两个账户调用过程是一个原子过程,软件事务内存(STM)提供了答案。

  STM提供了并发访问共享内存的管理控制机制。 STM利用两个概念 - 乐观和交易来管理共享的并发控制。

  (1). 乐观表示我们运行多个原子的平行块,假设将不会有错误。当我们完成后,我们检查是否有任何问题。如果没有发现任何问题,我们在原子块更新状态变量。如果我们发现问题,然后我们回滚,然后重试。乐观并发通常比任何其他的替代方法提供了更好的可伸缩性选项。


  (2).其次, STM提供模拟数据库事务处理类似的方式。 Java堆在STM的情况下,开始/提交和回滚数据集的事务。作为对象保存在内存中的状态,交易只实现了ACID中几个特点 - 原子性,一致性,隔离。
要管理多个分别运行在不同线程上交易作为一个原子块,使用概念CommitBarrier 。 CommitBarrier是一个跨多个线程之间的交易实现同步synchronization,一旦达到屏障,所有的交易自动提交。它是基于Java的CountDownLatch的。

  基于CommitBarrier的事务原理如下:每个Actor将阻塞等待彼此,直到每个Actor都参与的交易全部已完成。这意味着,即使成员可能分散在多个线程,但是也是作为CommitBarrier的成员,是一个单一的原子操作的一部分,如果任何一个堵塞的原子块抛出一个异常,或发生冲突,所有CommitBarrier成员将回滚。

  Akka提供一个结构协调actor之间的事务称为coordinated.coordinated,它是用来定义事务边界在交易事务开始时,coordinated.coordinate的()方法被用来增加所有成员将参加同一个事务上下文。

stm

以转账为案例:

为了确保帐户中的资金转移是发生在一个同步的方式下1,我们需要执行以下:

  • 在帐户对象中有一个状态变量需要参与交易的,应该是交易的引用类型。
  • 信用卡和借记卡的帐户对象中操作需要是原子的。
  • 在传输对象,需要定义事务边界的,帐户对象必须参加同一个事务上下文。
  • 此外,我们定义了主管政策在TransferActor和BankActor处理交易异常:

对上面一张图进行如下划分:

相关源码见:Akka框架STM

Agent使用

akka还提供Agent的原子操作使用,Agent STM源码下载

Akka STM 提供两个 Ref和 Agent:. Ref (Transactional References事务引用)提供访问多个实体协同的 同步. Agent提供对单个实体访问非协同的异步访问。Agent提供不协调异步访问,将意味着我们需要等待,直到所有的更新已经完成,Agents提供了非阻塞的读操作。

如果我们需要多个操作读写一个共享变量,使用Agent标识如下:

public class Stock {
        private String symbol;
        private Agent<Float> price;

价格的更改是需要锁的,这里是Agent。

读操作:

 

   Float stockTicker = stock.getPrice().get();

写操作:

 stock.getPrice().send(new Function<Float, Float>() {
                                public Float apply(Float i) {
                                        return i + 10;
                                }
                        });