群组首页
→
编程语言
→
erlang
→
知识库
→
Programming Erlang读书笔记
→
Programming Erlang读书笔记8: Concurrency Programming
原创作者: hideto
阅读:1988次
评论:1条
更新时间:2011-06-01
在Erlang里:
1,创建和销毁进程非常快
2,进程间发送消息非常快
3,在所有的操作系统间进程行为一致
4,可以有大量的进程
5,进程不共享内存并且完全独立
6,与进程交互的唯一途径是发送消息
Concurrency Primitives
Example
Client-Server通信时需要通过self()传递client端PID
自定义让当前进程sleep T毫秒的方法
自定义Timer
每个进程都有一个mailbox
发送消息到该进程时,消息被放入mailbox
当程序运行到receive语句时,启动一个timer
读取mailbox中的第一条消息,匹配Pattern1,2,...,如果消息匹配了,则从mailbox中删除掉,并执行该Pattern后的表达式
如果receive语句中没有匹配的Pattern,则将该消息从mailbox中删除并放入save queue,然后下一条消息进来匹配
如果mailbox中没有一条消息是匹配成功的,则进程suspend并等待下一次新的消息进来,下次有新消息时save queue里的消息不会再匹配
一旦有消息匹配,则已经放入save queue的消息按到达进程的顺序重新进入mailbox,如果设置了timer,则清空save queue
如果在等待消息时timer到点,则执行ExpressionsTimeout表达式并将保存的消息按到达进程的顺序放入mailbox
publishing一个process identifier,这样系统里所有process都可以和这个process交互,发布的process称为registered process
BIFs:
Example
Example2
Concurrent Program Template
在loop里receive之后马上又调用loop,则loop称为tail-recursive方法
如果我们写一个方法F,F never returns,则需要确保在调用F之后不会调用其他方法,也不要将F用于List或Tuple的constructor,否则内存溢出
spawn with MFA:
使用Mod名、Func名和Args列表(成为一个MFA)来显式的调用spawn是确保系统动态加载代码(热修改)的正确方式
spawn with funs则不会动态加载代码
作业
Erlang Ring Benchmark
1,创建和销毁进程非常快
2,进程间发送消息非常快
3,在所有的操作系统间进程行为一致
4,可以有大量的进程
5,进程不共享内存并且完全独立
6,与进程交互的唯一途径是发送消息
Concurrency Primitives
Pid = spawn(Fun) Pid!Message receive Pattern1 [when Guard1] -> Expressions1; Pattern2 [when Guard2] -> Expressions2; ... after Time -> Expressions end
Example
-module(area_server). -export([loop/0]). loop() -> receive {rectangle, Width, Ht} -> io:format("Area of rectangle is ~p~n", [Width * Ht]), loop(); {circle, R} -> io:format("Area of circle is ~p~n", [3.14 * R * R]), loop(); Other -> io:format("I don't know what the area of a ~p is. ~n", [Other]), loop() end.
Client-Server通信时需要通过self()传递client端PID
-module(area_server). -export([start/0, area/2). start() -> spawn(fun loop/0). area(Pid, What) -> rpc(Pid, What). rpc(Pid, Request) -> Pid ! {self(), Request}, receive {Pid, Response} -> Response end. loop() -> receive {From, {rectangle, Width, Ht}} -> From ! {self(), Width * Ht}, loop(); {From, {circle, R}} -> loop(); {From, Other} -> From ! {self(), {error, Other}}, loop() end. %%%%%%%%%%%%% 1> Pid = area_server:start(). <0.36.0> 2> area_server:area(Pid, {rectangle, 10, 8}). 80 3> area_server:area(Pid, {circle, 4}). 50.2645
自定义让当前进程sleep T毫秒的方法
sleep(T) -> receive after T -> true end.
自定义Timer
-module(stimer). -export([start/2, cancel/1]). start(Time, Fun) -> spawn(fun() -> timer(Time, Fun) end). cancel(Pid) -> Pid ! cancel. timer(Time, Fun) -> receive cancel -> void after Time -> Fun() end.
每个进程都有一个mailbox
发送消息到该进程时,消息被放入mailbox
当程序运行到receive语句时,启动一个timer
读取mailbox中的第一条消息,匹配Pattern1,2,...,如果消息匹配了,则从mailbox中删除掉,并执行该Pattern后的表达式
如果receive语句中没有匹配的Pattern,则将该消息从mailbox中删除并放入save queue,然后下一条消息进来匹配
如果mailbox中没有一条消息是匹配成功的,则进程suspend并等待下一次新的消息进来,下次有新消息时save queue里的消息不会再匹配
一旦有消息匹配,则已经放入save queue的消息按到达进程的顺序重新进入mailbox,如果设置了timer,则清空save queue
如果在等待消息时timer到点,则执行ExpressionsTimeout表达式并将保存的消息按到达进程的顺序放入mailbox
publishing一个process identifier,这样系统里所有process都可以和这个process交互,发布的process称为registered process
BIFs:
register(AnAtom, Pid) unregister(AnAtom) whereis(AnAtom) -> Pid | undefined registered() -> [AnAtom::atom()]
Example
1> Pid = spawn(fun area_server:loop/0). <0.51.0> 2> register(area, Pid). true 3> area ! {rectangle, 4, 5}. Area of rectangle is 20 {rectangle,4,5}
Example2
-module(clock). -export([start/2, stop/0]). start(Time, Fun) -> register(clock, spawn(fun() -> tick(Time, Fun) end)). stop() -> clock ! stop. tick(Time, Fun) -> receive stop -> void after Time -> Fun(), tick(Time, Fun) end. %%%%%%%%%%%%%%%%%% 1> clock:start(5000, fun() -> io:format("TICK ~p~n", [erlang:now()]) end). 2> clock:stop().
Concurrent Program Template
-module(ctemplate). -compile(export_all). start() -> spawn(fun() -> loop([]) end). rpc(Pid, Request) -> Pid ! {self(), Request}, receive {Pid, Response} -> Response end. loop(X) -> receive Any -> io:format("Received:~p~n", [Any]), loop(X) end.
在loop里receive之后马上又调用loop,则loop称为tail-recursive方法
如果我们写一个方法F,F never returns,则需要确保在调用F之后不会调用其他方法,也不要将F用于List或Tuple的constructor,否则内存溢出
spawn with MFA:
spawn(Mod, FuncName, Args)
使用Mod名、Func名和Args列表(成为一个MFA)来显式的调用spawn是确保系统动态加载代码(热修改)的正确方式
spawn with funs则不会动态加载代码
作业
Erlang Ring Benchmark
1 楼 wrj913 2011-11-29 11:34