zoukankan      html  css  js  c++  java
  • ellang 中进程异步通信中的信箱与保序

    erlang 进程通讯中 执行到 receive 语句时 如果信箱没有消息可以匹配时会暂停等待消息. 

    go() ->
        register(echo, spawn(test_pid,loop,[])),
        echo ! {self(), hello},
        receive
            {_Pid,Msg} ->
                io:format("~w~n",[Msg])
        end.
        %%Pid ! stop.
    
    loop() ->
        io:format(" loop start~n", []),
        receive
            {From, Msg} ->
                io:format(" loop : ~w | ~w~n", [From, Msg]), From ! {self(), Msg},
                loop();
            stop  -> io:format(" loop : ~w~n", [stop]), true
            %%    true
        end.

    由于信箱是先进先出,向同一个进程发送的消息,处理返回一定是保序的。 但这只限于一直不出错,匹配成功的情况,比如 revecie支持 timeOut, timeOut 后 进程将不在主动响应, 但是还能接收信息.

    read(Db, Key) ->
        Db ! {self(), {read, Key}},
        receive
            {read, R} -> {ok, R};
            {error, Reason} -> {error, Reason}
        after 10000 -> {error, timeout}
        end.
    
    db() ->
        receive
            {Pid, {read, 2}} -> Pid ! {read, 2},db();
            {Pid, {read, 3}} -> Pid ! {read, 3},db();
            {Pid, {read, 5}} -> Pid ! {error, "not Reason"},db()
        end.

    假如 有以下调用(Db 是个查询进程,查询完毕会给当前进程返回查询结果)

    read(Db, 1).

    read(Db, 2).

    //after 1500

    read(Db, 6).

    如果 read(Db, 1). 触发了timeout,  而且 read(Db, 2). 返回了{read, R}. 那么这时信箱处于阻塞状态,当read(Db,6).执行时, 会从信箱中取出第一条匹配返回. 所以 read(Db, 6).会返回 {ok, 2}.

    如果是在终端直接运行测试,可以这样写

    read(Db, Key) ->
        Db ! {self(), {read, Key}},
        receive
            {read, R} -> {ok, R};
            {error, Reason} -> {error, Reason}
        after 10000 -> test(self()), {error, timeout}
        end.
    
    db() ->
        receive
            {Pid, {read, 2}} -> Pid ! {read, 2},db();
            {Pid, {read, 3}} -> Pid ! {read, 3},db();
            {Pid, {read, 5}} -> Pid ! {error, "not Reason"},db()
        end.
    
    test(Pid) ->
        Pid ! {read, 2}.

    在timeout 的时候往信箱里塞一条信息,然后你会看到

    所以这时候,信箱的顺序就是错乱的, 那解决办法呢,一种是每次匹配前清理上一条消息,另一种则是加个唯一标识收到消息时匹配下是不是自己要的信息.

  • 相关阅读:
    Laravel 安装&基本介绍
    centos7 vi 打开文件 中文乱码问题记录
    Linux-CentOS7下安装LNMP环境笔记
    PHP Socket or TCP 连接错误信息显示乱码问题处理
    MySQL5.7的json数据格式的问题
    JS格式化显示json数据
    Go学习笔记之框架Beego安装
    ThinkPHP框架使用笔记
    郁闷了几天的问题终于解决了
    eclipse安装spring插件
  • 原文地址:https://www.cnblogs.com/bobolive/p/3171076.html
Copyright © 2011-2022 走看看