erlang这门语言的优势主要在于多核编程,编写强大高可用的程序离不开otp框架。otp中主要的行为模式gen_server,虽名为通用服务器,但gen_server的代码并不天生具有处理并发请求的能力,实际上一个gen_server写成的模块是运行在一个线程中的,所有针对它的请求都是序列化处理的,因此gen_server并不具有自动并行处理的能力,还得靠程序员自己实现并行。注意gen_server:call(或者cast)都是这样。
程序员自己如何处理呢?大家知道erlang程序的进程是非常“廉价”的,将任务在spawn出来的进程中处理即可。
erlang并发编程模板如下:
-module(ctemplate). -compile(export_all). %% start %% %% @spec start() -> pid() start() -> % explicit MFA (module, function, args list) enables dynamic code upgrades spawn(ctemplate, loop, [[]]). %% remote call %% %% @spec rpc(pid(), any()) -> any() rpc(Pid, Request) -> Pid ! {self(), Request}, receive % Pid is in the pattern match to avoid grabbing messages from all % processes ... {Pid, Response} -> Response end. %% receive loop handler %% %% @spec loop(any()) -> none() loop(X) -> receive Any -> io:format("Received:~p~n", [Any]), % tail recursion: this should be last call, % so it won't consume any stack space loop(X) end.
gen_server 的并发处理是在handle的回调函数中使用spawn,如下:
handle_call(Req, From, State) -> Handler = State#state.store_handler, spawn(fun(Req) -> Res = ......, % 在此处理计算得到结果 gen_server:reply(From, Res) % 将结果返回给调用者 end), {noreply, State}; % 直接返回
使用spawn需要注意 如果你的程序中使用进程字典保存全局变量,需要使用其他方式处理。