Erlang Gen_call vs Gen_cast

use*_*708 3 erlang erlang-otp

Erlang OTP表示gen_server:call同步并且gen_server:cast是异步的.

经过测试,我发现gen_server:call是同步的.但是,gen_server:cast 会将消息发送到邮箱,但并未同时运行任务.

如何创建多个进程来运行?

-module(example_gen).
-behaviour(gen_server).
-export([start_link/0]).
-export([init/1,
    handle_call/3,
    handle_cast/2,
    handle_info/2,
    terminate/2,
    code_change/3]).

 -export([
      add_bycall/2,
      add_bycast/2
   ]).

   -define(SERVER, ?MODULE).
   -record(state, {}).


add_bycall(Key, Value) ->
   gen_server:call(?SERVER, {bycall, Key, Value}).

 add_bycast(Key, Value) ->
      gen_server:cast(?SERVER, {bycast, Key, Value}).


 example(Key, Value) ->
       timer:sleep(2000),
      io:format("finished [~p, ~p] at [~p] ~n", [Key, Value, erlang:system_time(milli_seconds)]).

start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

init([]) ->
   {ok, #state{}}.


handle_call({bycall, Key, Value}, _From, State) ->
      example(Key, Value),
      {reply, ok, State};
  handle_call(_Request, _From, State) ->
     {reply, ok, State}.


 handle_cast({bycast, Key, Value}, State) ->
    example(Key, Value),
      {noreply, State};
 handle_cast(_Request, State) ->
       {noreply, State}.


handle_info(_Info, State) ->
   {noreply, State}.

 terminate(_Reason, _State) ->
   ok.

 code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
Run Code Online (Sandbox Code Playgroud)

运行代码

[example_gen:add_bycall(K, K) ||  K <-  lists:seq(1, 10) ].

[example_gen:add_bycast(K, K) ||  K <-  lists:seq(1, 10) ].
Run Code Online (Sandbox Code Playgroud)

Hyn*_*dil 6

术语同步异步与术语串行并行正交.gen_server:call/2,3与调用者同步,并与调用者gen_server:cast/2异步.一个人执行的工作gen_server总是串行的,因为它是由一个进程执行的.

在这种情况下,异步同步的术语是什么.如果你有代码

gen_server:call(S, foo),
bar(),
Run Code Online (Sandbox Code Playgroud)

触发的工作foo始终在之前执行,bar/0并且bar/0始终在工作foo完成后执行.因此foo并且bar/0同步的.如果你有代码

gen_server:cast(S, foo),
bar(),
Run Code Online (Sandbox Code Playgroud)

触发的工作foo可以bar/0在SMP系统之前以及之后甚至并行执行.因此foo并且bar/0异步的.调用者被调用者之间的同步很重要.