Erlang02_并发编程(2)

总篇:8

编辑于 2025/5/1 22:00

截稿于: 2025/5/1 23:44

上一篇介绍了并发编程基础部分,接下来是进阶1/2 部分:并发编程的错误处理。

原语

  1. true = link(Pid)
link(Pid): 当前进程链接Pid进程。
  1. true = unlink(Pid)
unlink(Pid):删除当前进程与Pid的链接关系。
  1. spwn_link(Fun)
spwn_link(Fun):创建进程时将创建的进程链接到创建该线程的线程。
  1. process_flag(trap_exit,true)
process_flag(trap_exit,true):进程会将收到的退出信号转换为消息,而不是直接终止,
也叫做将当前进程设置为系统进程,可能是因为系统进程不会在收到退出信号后直接终止本进程吧。
  1. none = exit(Why)
exit(Why):主动终止本进程并发送Why给所链接的其他进程,发送的格式{'EXIT',Pid,Why},其中Pid为发送Why的进程Pid,Why为进程终止原因。
系统进程可通过receive {'EXIT',Pid,Why} 接收该消息进行处理,其他链接进程会一并终止。

链接进程

  1. 一个进程发生不可修复错误导致进程死亡需要被其他进程知晓并处理,能够达成以上目的的方法就是链接两个或多个进程,link或spawn_link。链接通常成对成立,但又可发生交叉:

画板

上图有三个链接进程对:

A<->B, A<->C,B<->C

  1. 链接之后又怎样?这里先要知道:当一个进程发生未catch的错误或者主动使用原语exit(Why)退出(死亡)的时候,进程会向与他链接的进程发送退出信号:{'EXIT,Pid,Why},非系统进程接收后会直接跟着退出(死亡),而系统进程可以通过receive {'EXIT',Pid,Why} 来处理错误,避免直接退出(死亡).

改进聊天室

基于以上知识,可以改进上一篇中的简易聊天室:

  1. chater文件合一
  2. 服务器强制关闭
  3. 客户端主动退出聊天室
-module(chat_server).
-export([start/0]).

start() ->
    Pid = spawn(fun() ->
        process_flag(trap_exit, true),
        loop([])
    end),
    register(chat_server, Pid),
    Pid.

loop(Clients) ->
    receive
        stop ->
            io:format("chat_server stopped by admin~n"),
            exit("chat_server stopped by admin");
        {'EXIT', Pid, Why} ->
            io:format("chat_server received exit signal from ~p with reason ~p~n", [Pid, Why]),
            loop(lists:delete(Pid, Clients));
        {From, exit} ->
            io:format("chat_server received exit command from ~p~n", [From]),
            From ! {self(), exit},
            loop(lists:delete(From, Clients));
        {From, Message} ->
            NewClients = add_unique(From, Clients),
            io:format("chat_server received message from ~p: ~p~n", [From, Message]),
            lists:foreach(fun(Pid) -> Pid ! {From, Message} end, Clients),
            loop(NewClients);
        {From, Message, Pids} ->
            NewClients = add_unique_list(Pids, Clients),
            io:format("chat_server received message from ~p: ~p~n", [From, Message]),
            lists:foreach(fun(Pid) -> Pid ! {From, Message} end, Pids),
            loop(NewClients)
    end.

add_unique_list([], List) ->
    List;
add_unique_list([H | T], List) ->
    NewList = add_unique(H, List),
    add_unique_list(T, NewList).
add_unique(Element, List) ->
    case lists:member(Element, List) of
        true -> List;
        false -> [Element | List]
    end.


以上代码待完善。

posted on 2025-05-01 23:48  依只  阅读(3)  评论(0)    收藏  举报

导航