erlang中的process——程序是輕量級的,並且程序間無共享。查了很多資料,似乎沒人說清楚輕量級程序算是什麼概念,繼續查詢中。。。閒話不提,進入併發程式設計的世界。本文算是學習筆記,也可以說是《concurrent programming in erlang》第五張的簡略翻譯。
1.程序的建立
程序是一種自包含的、分隔的計算單元,並與其他程序併發執行在系統中,在程序間並沒有乙個繼承體系,當然,應用開發者可以設計這樣乙個繼承體系。
程序的建立使用如下語法:
pid = spawn(module, functionname, argumentlist)
spawn接受三個引數:模組名,函式名以及引數列表,並返回乙個代表建立的程序的識別符號(pid)。
如果在乙個已知程序pid1中執行:
pid2 = spawn(mod, func, args)
那麼,pid2僅僅能被pid1可見,erlang系統的安全性就構建在限制程序擴充套件的基礎上。
2.程序間通訊
erlang程序間的通訊只能通過傳送訊息來實現,訊息的傳送使用!符號:
pid ! message
其中pid是接受訊息的程序標記符,message就是訊息。接受方和訊息可以是任何的有效的erlang結構,只要他們的結果返回的是程序標記符和訊息。
訊息的接受是使用receive關鍵字,語法如下:
receive
message1 [when guard1] ->
actions1 ;
message2 [when guard2] ->
actions2 ;
end
每乙個erlang程序都有乙個「郵箱」,所有傳送到程序的訊息都按照到達的順序儲存在「郵箱」裡,上面所示的訊息message1,message2,當它們與「郵箱」裡的訊息匹配,並且約束(guard)通過,那麼相應的actionn將執行,並且receive返回的是actionn的最後一條執行語句的結果。erlang對「郵箱」裡的訊息匹配是有選擇性的,只有匹配的訊息將被觸發相應的action,而沒有匹配的訊息將仍然保留在「郵箱」裡。這一機制保證了沒有訊息會阻塞其他訊息的到達。
訊息到達的順序並不決定訊息的優先順序,程序將輪流檢查「郵箱」裡的訊息進行嘗試匹配。訊息的優先級別下文再講。
如何接受特定程序的訊息呢?答案很簡單,將傳送方(sender)也附送在訊息當中,接收方通過模式匹配決定是否接受,比如:
pid !
給程序pid傳送訊息,利用self過程得到傳送方作為訊息傳送。然後接收方:
receive
->
end
通過模式匹配決定只有pid1程序傳送的訊息才接受。
3.一些例子
僅說明下書中計數的程序例子,我新增了簡單注釋:
-module(counter).
-compile(export_all).
% start(),返回乙個新程序,程序執行函式loop
start()->spawn(counter, loop,[0]).
% 呼叫此操作遞增計數
increment(counter)->
counter!increament.
% 返回當前計數值
value(counter)->
counter!,
receive
->
%返回給呼叫方
value
end.
%停止計數
stop(counter)->
counter!.
loop(val)->
receive
%接受不同的訊息,決定返回結果
increament->
loop(val+1);
->
from!,
loop(val);
stop->
true;
%不是以上3種訊息,就繼續等待
other->
loop(val)
end.
呼叫方式:
1> counter1=counter:start().
<0.30.0>
2> counter:value(counter1).
0
3> counter:increment(counter1).
increament
4> counter:value(counter1).
1
基於程序的訊息傳遞機制可以很容易地實現有限狀態機(fsm),狀態使用函式表示,而事件就是訊息。具體不再展開
4.超時設定
erlang中的receive語法可以新增乙個額外選項:timeout,類似:
receive
message1 [when guard1] ->
actions1 ;
message2 [when guard2] ->
actions2 ;
after
timeoutexpr ->
actionst
end
after之後的timeoutexpr表示式返回乙個整數time(毫秒級別),時間的精確程度依賴於erlang在作業系統或者硬體的實現。如果在time毫秒內,沒有乙個訊息被選中,超時設定將生效,也就是actiont將執行。time有兩個特殊值:
1)infinity(無窮大),infinity是乙個atom,指定了超時設定將永遠不會被執行。
2) 0,超時如果設定為0意味著超時設定將立刻執行,但是系統將首先嘗試當前「郵箱」裡的訊息。
超時的常見幾個應用,比如掛起當前程序多少毫秒:
sleep(time) ->
receive
after time ->
true
end.
比如清空程序的「郵箱」,丟棄「郵箱」裡的所有訊息:
flush_buffer() ->
receive
anymessage ->
flush_buffer()
after 0 ->
true
end.
將當前程序永遠掛起:
suspend() ->
receive
after
infinity ->
true
end.
超時也可以應用於實現定時器,比如下面這個例子,建立乙個程序,這個程序將在設定時間後向自己傳送訊息:
-module(timer).
-export([timeout/2,cancel/1,timer/3]).
timeout(time, alarm) ->
spawn(timer, timer, [self(),time,alarm]).
cancel(timer) ->
timer ! .
timer(pid, time, alarm) ->
receive
->
true
after time ->
pid ! alarm
end.
5、註冊程序
為了給程序傳送訊息,我們需要知道程序的pid,但是在某些情況下:在乙個很大系統裡面有很多的全域性servers,或者為了安全考慮需要隱藏程序pid。為了達到可以傳送訊息給乙個不知道pid的程序的目的,我們提供了註冊程序的辦法,給程序們註冊名字,這些名字必須是atom。
基本的呼叫形式:
register(name, pid)
將name與程序pid聯絡起來
unregister(name)
取消name與相應程序的對應關係。
whereis(name)
返回name所關聯的程序的pid,如果沒有程序與之關聯,就返回atom:undefined
registered()
返回當前註冊的程序的名字列表
6.程序的優先順序
設定程序的優先順序可以使用bifs:
process_flag(priority, pri)
pri可以是normal、low,預設都是normal
優先順序高的程序將相對低的執行多一點。
7.程序組(process group)
所有的erlang程序都有乙個pid與乙個他們共有的稱為group leader相關聯,當乙個新的程序被建立的時候將被加入同乙個程序組。最初的系統程序的group leader就是它自身,因此它也是所有被建立程序及子程序的group leader。這就意味著erlang的程序被組織為一棵tree,其中的根節點就是第乙個被建立的程序。下面的bifs被用於操縱程序組:
group_leader()
返回執行程序的group leader的pid
group_leader(leader, pid)
設定程序pid的group leader為程序的leader
8.erlang的程序模型很容易去構建client-server的模型,書中有一節專門討論了這一點,著重強調了介面的設計以及抽象層次的隔離問題,不翻譯了。
Erlang程式設計入門之併發程式設計 程序
使用erlang而不是其他函式式語言的乙個很主要的原因就是 erlang具有處理併發和分布式計算的程式設計能力。我們這裡說的併發是指程式可以在同乙個時點處理多個執行緒的執行。例如,現代作業系統可以允許你使用word的同時使用excel,並且還開著乙個電子郵件客戶端程式,乙個列印的任務在後台也在執行著...
erlang 併發程式設計 併發01
erlang純訊息傳遞式語言 特點 建立新程序 通過pid給次執行緒發訊息,mod模組,func方法,args傳入引數 pid spawn mod,func,args 新起乙個併發程序執行fun,fun的屬性是當前值 pid spawn fun 傳送訊息 pid message接受訊息 receiv...
Erlang併發程式設計 五 bigwig
bigwig erlang web 監控工具。參考資料 git clone 修改rebar.config,指定版本 預設是r14,如果當前系統使用r15需要則修改 獲取依賴。rebar get deps start ensure started crypto ensure started sasl ...