iT邦幫忙

DAY 29
2

蠻可愛的 Erlang 與 Elixir系列 第 29

Elixir 的 Concurrency

Erlang 與 Elixir的 Concurrency 原理

前面我們已經看過Erlang的Concurrency一些實例.
今天來講一下原理.
Erlang的process會在名稱為BEAM的VM上面執行,如下圖所示:

BEAM deafult會產生數個scheduler,對應系統CPU,例如使用4核心的機器,
就會產生4個scheduler.
裡面執行的Erlang process,與系統的process不同.是很輕量的,
使用的記憶體也很少,基本使用1-2KB.而且透過此種架構,可以有
效發揮CPU的運算能力,我們無須寫複雜的程式碼,細節都由Erlang
幫我們處理好了.各個process是獨立的,因為記憶體不共享,變數
不能被改變,若某一個process崩潰,就被隔離,不會影響到整個系統.
在Erlang的世界,百萬個process在跑,是稀鬆平常的事.
Elixir身為Erlang的 meta programming language,一樣可以使用
如此強大的機制.其實Elixir的程式,編譯後就是Erlang的beam檔.
接著我們來看看Elixir的process吧.

Elixir 的 process

在Elixir中建立process,一樣是使用spawn.
為了說明方便起見,先建立一個function,會sleep兩秒,
模擬執行query.

iex(1)> run_query = fn(query_def) ->
...(1)>   :timer.sleep(2000)
...(1)>   "#{query_def} result"
...(1)> end
#Function<6.90072148/1 in :erl_eval.expr/5>

iex(2)> async_query = fn(query_def) ->
...(2)>   spawn(fn -> IO.puts(run_query.(query_def)) end)
...(2)> end
#Function<6.90072148/1 in :erl_eval.expr/5>

iex(3)> async_query.("query 1")
#PID<0.63.0>
query 1 result

接著我們學一下IP Man(葉問),打十個好了.

iex(4)> Enum.each(1..10, &(async_query.("query #{&1}")))
:ok
query 2 result
query 1 result
query 9 result
query 8 result
query 7 result
query 6 result
query 5 result
query 4 result
query 3 result
query 10 result

訊息傳遞

訊息傳送使用 send/2, 接收方使用
receive do
pattern_1 -> do_something
pattern_2 -> do_anotherthing
end
這樣的方式來接收.

來看範例:

defmodule Spawn1 do
  def greet do
    receive do
      {sender, msg} ->
        send(sender, {:ok, "Hello #{msg}"})
    end
  end
end

# client
pid = spawn(Spawn1, :greet, [])
send(pid, {self, "Miku!"})

receive do
  {:ok, message} ->
    IO.puts message
end

執行結果:

iex(5)> c "spawn1.ex"
Hello Miku!
[Spawn1]

兩邊互相傳送訊息.有沒有注意到 IO.puts 把()省略了.
在Exixir 引用函數時,後面的() 可以省略.
上面程式可以改成:

defmodule Spawn1 do
  def greet do
    receive do
      {sender, msg} ->
        send sender, {:ok, "Hello #{msg}"}
    end
  end
end

# client
pid = spawn(Spawn1, :greet, [])
send pid, {self, "Miku!"}

receive do
  {:ok, message} ->
    IO.puts message
end

這樣可以避免函數的()過多,讓我們專注於整個流程與邏輯.

Elixir一樣具有 timeout,也是使用 after;
一樣可以把process註冊名稱.
這些部份,在前面Erlang的部份,都已經介紹過了,在此不重複.


上一篇
Elixir 的 Loops 與 iteration
下一篇
開放電信平台OTP 介紹
系列文
蠻可愛的 Erlang 與 Elixir30

尚未有邦友留言

立即登入留言