`
argan
  • 浏览: 129556 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Erlang 基础学习 6 Concurrent Programming

阅读更多
好戏开始了

Erlang 的程序由很多process组成,这些process和人很象:
• 都有自己的一份memory,并且不会互相影响
• 如果要影响别人的memory,都必须明确告诉对方,比如发个消息(说句话)啥的
• 当然,说了别人不一定听,还得确认一下,哥们,明白了么?
• 这些process如果挂了,会在最后吼出来:考,老子被零除!啊!
• 这样,其他的process就会知道,哦,谁谁谁挂了。
• 还有,process间还可以达成某总协议,比如说,一方挂了,另一方帮忙处理后事,之类的。
• 归纳一下就是:
• 1. Erlang程序是由很多进程组成,这些进程之间可以互相发消息。(这个进程和传统意义上操作系统里的进程是不一样的,只是概念上差不多)
• 2. 这些消息不一定能收到或者明白,如果要确认这一点的话,必须发送消息之后等回答
• 3. 两个进程可以结对,连接在一起,如果其中一方挂了,另一方会得到死因

Think of people in a room. The people are the processes. The people in the room have individual private memories; this is the state of a process. To change your memory, I talk to you, and you listen. This is sending and receiving messages. We have children; this is spawn. We die; this is a process exit.

这就是Erlang的模型。

和操作系统的进程相比,Erlang的进程
• 创建和销毁都很快
• 进程间发送消息很快
• 在所有操作系统上,这些进程都一样的工作
• 可以有非常大数量的进程,例如几十万,几百万?
• 进程之间没有共享内存,完全互相独立
• 进程间唯一的交互途径就是发送消息

The Concurrency Primitives

• 1. Pid = spawn(Fun).
• 或者 spawn(Module,Fun,Args). 推荐这种方式,动态更新代码有用
• 创建一个和调用者并行的新进程来执行Fun,可以通过返回的Pid来发送消息
• 2. Pid!Message
• 发送一条消息给Pid对应的进程,该语句返回Message本身,因此Pid1!Pid2!Pid3..!Message,就可以将Message发给所有这些进程
• 发送消息的过程是异步的
• 3. receive ... end
receive
    Pattern1 [when Guard1] ->
        Expressions1;
    Pattern2 [when Guard2] ->
        Expressions2;
    ...
end
• 当进程收到消息的时候,挨个匹配这些Pattern,如果匹配到就执行,否则匹配下一条,都没匹配到的话,就把消息保存起来

一个简单的例子
-module(area_server0).
-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.14159 * R * R]),
           loop();
       Other ->
           io:format("I don't know what the area of a ~p is ~n" ,[Other]),
           loop()
   end.
• 首先,在shell里起来 Pid = spawn(fun area_server0:loop/0).
• 然后就可以使用了 Pid ! {rectangle, 6, 10}.


Client-Server 结构
• Erlang里大量使用到C/S结构
• 这里的client和server都是erlang里的进程,都很轻量
• 可以在同一台机器也可以分布在不同的机器上
• 是按其职责来区分client和server的,client发送请求给server,然后server处理之后返回
• 和写信一样,要收到回信就要送过去自己的地址,要收到回答的消息,就必须告诉对方自己的地址(Pid)
-module(area_server_final).
-export([start/0, area/2]).

start() -> spawn(fun loop/0).  %% 启动

area(Pid, What) ->
    rpc(Pid, What).

rpc(Pid, Request) ->
    Pid ! {self(), Request},  %% 发送消息给server
    receive
        {Pid, Response} ->  %% 接收server发回的消息,通过Pid来确认
            Response
    end.

loop() ->
    receive
        {From, {rectangle, Width, Ht}} ->
            From ! {self(), Width * Ht},     %% 返回结果,并加上自己的身份self(),以确认确实是自己返回的
            loop();
        {From, {circle, R}} ->
            From ! {self(), 3.14159 * R * R},
            loop();
        {From, Other} ->
            From ! {self(), {error,Other}},
            loop()
    end.

erlang 创建进程有多快?

• Erlang的进程数限制,通过erlang:system_info(process_limit)可以得到,一般是32768(32位机器),要调整可以通过命令行
• erl +P 1000000 来设置
• erlang 创建进程非常快,非常非常快,可以自己试试看
• 在我的笔记本上得到的结果,看起来跑个60万没问题的,当然是什么活都没干,呵呵
8> processes:max(500000).
Maximum allowed processes:1000000
Process spawn time=4.32 (6.858) microseconds
ok
9> processes:max(600000).
Maximum allowed processes:1000000
Process spawn time=4.316666666666666 (6.801666666666667) microseconds
ok
10> processes:max(700000).
Maximum allowed processes:1000000
Process spawn time=4.571428571428571 (7.062857142857143) microseconds
• 使用的程序如下:

-module(processes).
-export([max/1]).
%% max(N)
%%   Create N processes then destroy them
%%   See how much time this takes
max(N) ->
    Max = erlang:system_info(process_limit),
    io:format("Maximum allowed processes:~p~n" ,[Max]),
    statistics(runtime),
    statistics(wall_clock),
    L = for(1, N, fun() -> spawn(fun() -> wait() end) end),
    {_, Time1} = statistics(runtime),
    {_, Time2} = statistics(wall_clock),
    lists:foreach(fun(Pid) -> Pid ! die end, L),
    U1 = Time1 * 1000 / N,
    U2 = Time2 * 1000 / N,
    io:format("Process spawn time=~p (~p) microseconds~n" ,
              [U1, U2]).
wait() ->
    receive
        die -> void
    end.
for(N, N, F) -> [F()];
for(I, N, F) -> [F()|for(I+1, N, F)].

接收消息时的超时
receive
     Pattern1 [when Guard1] ->
         Expressions1;
     Pattern2 [when Guard2] ->
         Expressions2;
     ...
after Time ->   %% 超时时间,单位millisecond
     Expressions
end
• receive 是在等待,因此我们可以轻松实现一个sleep
sleep(T) ->
    receive
    after T ->
       true
    end.
• 如果超时时间设置为0,表示马上超时,立即执行,但在此之前仍然会执行前面的pattern match
• 如果超时时间为infinity,表示永远不超时
• 利用receive ... after 可以轻易实现一个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.

接收消息
• 实际上,所有的发送给一个进程的消息都是保存在这个进程的邮箱里,当进程做receive的时候,就从邮箱里去取一条消息
• receive的实际工作过程是这样的
• 1. 执行receive的时候,启动一个timer(当然是设置了time out时间的情况下)
• 2. 从邮箱里取出第一条消息,进行匹配,如果匹配到某个规则,就从邮箱里删除这条消息,然后执行相应的代码
• 3. 如果没有匹配到任何一个pattern,就把消息移动到一个“保存队列”中,然后在取第二条,以此反复
• 4. 如果一条都没匹配上,进程就挂起等待新的消息进来,新消息进来的时候,只会那新到的消息去匹配,在“保存队列”里的消息不会再匹配过
• 5. 一旦有消息成功匹配,将“保存队列”里的消息按原来到达的次序放到邮箱里,清理timer
• 6. 如果在等待消息的过程中,timer到期了,将执行after 下的语句,同时把“保存队列”里的消息按原来顺序放回邮箱

Registered Processes

• 在erlang里,不知道进程的Pid就无法和他通信
• 但是有时需要让别的进程都和自己通信,这时可以使用registered process,实际上就是给自己起个名字,大家都用这个名字来通信
• register(AnAtom, Pid)  如果这个名字已经被注册了,注册将会失败
• unregister(AnAtom)  如果一个进程挂了,将会自动被取消注册
• whereis(AnAtom) -> Pid | undefined
• registered() -> [AnAtom::atom()]
• 例子,实现一个时钟
-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.

32> clock:start(1000,fun() -> io:format("Time is ~p~n",[erlang:now()] ) end).
true
Time is {1221,716569,346481}
Time is {1221,716570,350670}
Time is {1221,716571,355489}
Time is {1221,716572,358767}
Time is {1221,716573,362840}
33> clock:stop().
stop

分享到:
评论

相关推荐

    Concurrent Programming in ERLANG (P1-90)

    **并发编程在Erlang中的应用(Concurrent Programming in ERLANG)** 本标题及描述明确指出了文档的主要内容是关于如何在Erlang语言中进行并发编程。Erlang是一种通用、并发、强类型、垃圾回收的编程语言,特别适用...

    Concurrent Programming in ERLANG

    - 通过学习顺序编程的基础,读者可以更好地理解Erlang如何处理数据流和控制结构。 **1.2 数据类型** - Erlang中有多种基本数据类型,如整数、浮点数、原子等。 - 这些类型为构建复杂的数据结构提供了基础。 **1.3 ...

    erlang学习相关资料

    Joe的那篇erlang论文 Programming Erlang + 源码包 Erlang Programming Concurrent Programming in Erlang efficiecy guide 资源齐全.希望能帮到你.

    Concepts and Notations for Concurrent Programming

    《Concepts and Notations for Concurrent Programming》这篇论文由Gregory R. Andrews和Fred B. Schneider撰写,深入探讨了并行编程的核心概念和技术。尽管这是一篇较为古老的文章,但其内容仍然具有很高的参考价值...

    erlang programming

    Concurrent Programming in ERLANG可能深入讲解如何设计和管理并发进程,以及如何处理进程间的同步和异步通信。 3. **分布式系统**:“面对软件错误构建可靠的分布式系统.pdf”强调了Erlang在构建分布式系统时的...

    Erlang的那几本书

    Programming Erlang + 源码包 Erlang Programming Concurrent Programming in Erlang Joe的那篇erlang论文 efficiecy guide

    programming-erlang-software-for-a-concurrent-world

    Pragmatic Programmer,Pragmatic Programming,Pragmatic Bookshelf and the linking g device are trademarks of The Pragmatic Programmers,LLC. Every precaution was taken in the preparation of this book....

    Erlang_-_Concurrent_Functional_Programming_for_Telecommunications._A_Case_Study_of_Technology_Introd

    论文以实际案例为基础,重点介绍了一种并发函数式编程语言——Erlang。Erlang由爱立信公司的计算机科学实验室研发,并已作为开源软件提供给公众使用。目前,Erlang已在大约20个系统中得到应用,其中包括著名的ATM...

    Erlang and OTP in Action

    Erlang and OTP in Action teaches you to apply Erlang’s message passing model for concurrent programming–a completely different way of tackling the problem of parallel programming from the more ...

    erlang的学习pdf

    3. **书籍资料**:如《Programming Erlang: Software for a Concurrent World》是一本非常好的入门书籍。 通过以上介绍,我们不仅了解了Erlang的基础概念及其优势,还学习了如何安装配置Erlang环境以及简单的Erlang...

    erlang 设计指南

    "Programming Erlang: Software for a Concurrent World"是Joe Armstrong编写的经典书籍,深入探讨了Erlang的设计哲学和技术细节。 在Erlang中,并发是核心特性之一。通过轻量级进程(Lightweight Processes, LWP)...

    Programming Erlang

    ### 编程Erlang:面向并发世界的软件开发 #### 核心概念解析 **编程Erlang**这本书深入探讨了如何使用Erlang语言来编写高效、...对于那些希望在并发领域有所作为的开发者来说,学习Erlang绝对是一项值得投资的技能。

    Programming Elixir

    As a developer, you’ve probably heard that functional programming techniques help manage the complexities of today’s real-world, concurrent systems. You’re also investigating designs that help you ...

    Erlang程序设计[英文版]

    - **书籍推荐**:《Programming Erlang: Software for a Concurrent World》是一本很好的入门指南,由Erlang之父Joe Armstrong撰写,详细介绍了Erlang的基本概念和编程技巧。 - **在线课程**:许多在线教育平台提供...

    erlang 语言程序设计

    《Programming Erlang: Software for a Concurrent World》是一本非常好的入门书籍,它不仅介绍了Erlang的基本概念,还提供了丰富的实例和实践指导。此外,还可以参考官方文档和其他在线教程,积极参与社区交流,以...

Global site tag (gtag.js) - Google Analytics