首页 > Erlang并发教程 > 8.6 Erlang并发编程-创建和删除链接
2013
11-15

8.6 Erlang并发编程-创建和删除链接

BACK TOP文章索引

  1. 创建和删除链接
  2. 共0条评论

创建和删除链接

进程可以链接到其它进程和端口。进程间的链接都是双向的,也就是说,如果进程A链接到进程B,那么进程B也会自动链接到进程A。

通过执行BIF link(Pid)便可创建链接。调用link(Pid)时,若调用进程和Pid之间已经存在链接,则不会产生任何影响。

进程终止时,它所持有的链接都将被删除。也可以通过执行BIF unlink(Pid)显式删除链接。由于所有链接都是双向的,删除这一端到另一端的链接的同时,另一端的到这一端的链接也会被删除。若调用进程和Pid之间原本就没有链接,unlink(Pid)不会产生任何影响。

BIF spawn_link/3在创建新进程的同时还会在调用进程和新进程间建立链接。其行为可以定义为:

spawn_link(Module, Function, ArgumentList) ->
    link(Id = spawn(Module, Function, ArgumentList)),
    Id.

只不过spawnlink是原子方式执行的。这是为了避免调用进程在执行link之前就被EXIT信号杀死。尝试向一个不存在的进程发起链接将导致信号{'EXIT', Pid,noproc}被发送至link(Pid)的调用进程。

程序7.2中,函数start/1建立了若干以链式互联的进程,其中第一个进程的注册名为start(参见图7.1)。函数test/1向该注册进程发送消息。每个进程不断打印自己在链中的位置及收到的消息。消息stop令链中最后一个进程执行BIF exit(finished),该BIF将导致该进程异常终止。

程序7.2

-module(normal).
-export([start/1, p1/1, test/1]).

start(N) ->
    register(start, spawn_link(normal, p1, [N - 1])).

p1(0) ->
    top1();
p1(N) ->
    top(spawn_link(normal, p1, [N - 1]),N).

top(Next, N) ->
    receive
         X ->
             Next ! X,
             io:format("Process ~w received ~w~n", [N,X]),
             top(Next,N)
    end.

top1() ->
    receive
         stop ->
             io:format("Last process now exiting ~n", []),
             exit(finished);
         X ->
             io:format("Last process received ~w~n", [X]),
             top1()
    end.

test(Mess) ->
    start ! Mess.

我们启动三个进程(参见图7.1(a))

> normal:start(3).
true
../_images/7.1.png图7.1 进程退出信号的传递

然后向第一个进程发送消息123

> normal:test(123).
Process 2 received 123
Process 1 received 123
Last process received 123
123

再向第一个进程发送消息stop

> normal:test(stop).
Process 2 received stop
Process 1 received stop
Last process now exiting
stop

这条消息顺着进程链传递下去,我们将看到它最终导致链中最后一个进程的终止。这会引发一个发送给倒数第二个进程的EXIT信号,致其异常终止(图7.1(b)),接着又向第一个进程发送EXIT信号(图7.1(c)),于是注册进程start也异常终止(图 7.1(d))。

若这时再向注册进程start发送一条新消息,将由于目标进程不存在而失败:

> normal:test(456).
!!! Error in process <0.42.1> in function
!!!     normal:test(456)
!!! reason badarg
** exited: badarg **

留下一个回复

你的email不会被公开。