线程安全的演员运行未来的回调

时间:2016-09-15 09:16:40

标签: java multithreading scala akka

akka文档声明:

  

(...)你可以编写你的演员代码而不必担心并发性。

     

在幕后,Akka将在一组真实线程上运行多组actor,通常许多actor共享一个线程,一个actor的后续调用最终可能会在不同的线程上进行处理。 Akka确保此实现细节不会影响处理actor状态的单线程。

但是,假设我正构建一个Future,并将其传递给事件处理线程中的回调。例如,使用ask模式:

import React from 'react';
import { Match, Link, Miss } from 'react-router';
import DocumentMeta from 'react-document-meta';

import MainLayout from './Layouts/MainLayout';
import Homepage from './containers/Homepage/Homepage';
import Game from './containers/Game/Game';
import NotFound from './containers/NotFound/NotFound';

export const routes = {
  homepage: {
    exactly: true,
    pattern: '/',
    label: 'About React Lego',
    component: Homepage
  },
  game: {
    pattern: '/game',
    label: 'Star Wars Trivia',
    component: Game
  }
};

const passPropsToRoute = ({ route, props }) => (
  <span>
    <DocumentMeta title={ route.title } />
    <route.component {...props} routes={route.routes}/>
  </span>
);

const matchWithSubRoutes = (key, i) => {
  const route = routes[key];
  return (<Match { ...route } key={ i } render={(props) => passPropsToRoute({ route, props })} />);
};

export function makeRoutes() {
  return (
    <MainLayout>
      {Object.keys(routes).map(matchWithSubRoutes)}
      <Miss title={`${siteTitle} - Page Not Found`} component={ NotFound } />
    </MainLayout>
  );
}

这是否意味着回调永远不会与事件处理线程同时执行?因此,可以安全地修改actor状态而不必担心同步?

2 个答案:

答案 0 :(得分:3)

  

这是否意味着回调永远不会与之同时执行   事件处理线程

在你的情况下。回叫可以同时执行。

解释:演员的线程安全来自confinement。即,当演员收到消息时,Akka保证您的演员身体只会被一个线程一次执行。

现在,同时,如果你产生一个线程并尝试改变一些内部状态(如变量或其他东西),那么akka无法控制它。线程的消息消耗和未来的主体执行都可以并行发生。

  

因此,可以安全地修改演员状态而不用担心   同步?

如果你的未来阻止处理身体从未使用的变量,那么你可能不需要同步。万一它,你需要它。

答案 1 :(得分:0)

当你的意思是“//修改演员状态”对自己做一个爆炸(!)然后它应该是okey,但如果它真的修改了Actor状态那么它就是NOK。

Actor的threadsafe属性是由于它的邮箱和actor属性,它一次只处理一条消息。如果您不使用Actor的邮箱来修改它的状态,那么您需要自己锁定/同步这些可变状态。 (有关更好的说明,请参阅此链接:http://doc.akka.io/docs/akka/snapshot/general/jmm.html#Actors_and_the_Java_Memory_Model