2016-07-21 37 views
3

Erlang OTP表示gen_server:call是同步的,而gen_server:cast是异步的。Erlang Gen_call vs Gen_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}. 

运行代码

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

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

回答

6

条款同步异步正交术语串行平行gen_server:call/2,3与呼叫者同步,gen_server:cast/2与呼叫者异步。一个gen_server执行的工作始终是串行的,因为它由一个进程执行。

什么条件异步同步意味着在这种情况下。如果你有代码bar/0之前一直执行

gen_server:call(S, foo), 
bar(), 

工作由foo触发和工作foo结束后bar/0始终执行。因此foobar/0同步。如果你有一些代码可以bar/0之前以及之后,甚至在SMP系统上并行执行

gen_server:cast(S, foo), 
bar(), 

工作由foo触发。因此foobar/0异步同步之间的事项来电被呼叫者

+0

谢谢。它解释了很多。 – user3644708