process in Erlang - the process is lightweight and there is no sharing between processes. After checking a lot of information, no one seemed to explain what the concept of lightweight processes is. We continue to search. . . Without talking about gossip, enter the world of concurrent programming. This article is considered a study notes, and it can also be said to be a brief translation of the fifth picture of "Concurrent Programming in ERLANG".
1. Process creation
A process is a self-contained, separated computing unit and runs concurrently in the system with other processes. There is no inheritance system between processes. Of course, application developers can design such an inheritance system.
The creation of the process uses the following syntax:
Pid = spawn(Module, FunctionName, ArgumentList)
spawn takes three parameters: module name, function name, and parameter list, and returns an identifier (Pid) representing the created process.
If executed in a known process Pid1:
Pid2 = spawn(Mod, Func, Args)
Then, Pid2 can only be visible to Pid1, and the security of the Erlang system is built on the basis of restricting process expansion.
2. Inter-process communication
Communication between Erlang processes can only be achieved by sending messages, and the sending of messages uses the! symbol:
Pid ! Message
where Pid is the process tag that accepts messages, and Message is the message. The recipient and message can be any valid Erlang structure as long as their result returns a process tag and message.
The acceptance of messages is to use the receive keyword, and the syntax is as follows:
receive
Message1 [when Guard1] ->
Actions1 ;
Message2 [when Guard2] ->
Actions2 ;
end
Each Erlang process has a "mailbox". All messages sent to the process are stored in the "mailbox" in the order of arrival. The messages Message1 and Message2 shown above match the messages in the "mailbox" and the constraint (Guard) passes, then the corresponding ActionN will be executed, and the receive returns the result of the last execution statement of ActionN. Erlang is selective for matching messages in the "mailbox". Only matched messages will be triggered by the corresponding action, while non-matched messages will remain in the "mailbox". This mechanism ensures that no messages will block the arrival of other messages.
The order in which messages arrive does not determine the priority of the messages. The process will take turns checking the messages in the "emailbox" to try to match. The priority level of the message will be discussed later.
How to accept messages from specific processes? The answer is very simple. The sender is also attached to the message. The receiver decides whether to accept it through pattern matching, such as:
Pid ! {self(),abc}
Send a message {self(),abc} to the process Pid, and use the self process to get the sender to send as a message. Then the receiver:
receive
{Pid1,Msg} ->
end
Only messages sent by the Pid1 process will be accepted through pattern matching.
3. Some examples
Only explain the process examples of counting in the following book, I added a simple comment:
-module(counter).
-compile(export_all).
% start(), returns a new process, the process executes the function loop
start()->spawn(counter, loop,[0]).
% Call this operation to increment the count
increment(Counter)->
Counter!increament.
% Returns the current count value
value(Counter)->
Counter!{self(),value},
receive
{Counter,Value}->
% is returned to the caller
Value
end.
%Stop counting
stop(Counter)->
Counter!{self(),stop}.
loop(Val)->
receive
% accepts different messages and decides to return the result
increament->
loop(Val+1);
{From,value}->
From!{self(),Val},
loop(Val);
stop->
true;
% is not the above three messages, so continue to wait
Other->
loop(Val)
end.
Call method:
1> Counter1=counter:start().
<0.30.0>
2> counter:value(Counter1).
0
3> counter:increment(Counter1).
increament
4> counter:value(Counter1).
1
Process-based messaging mechanisms can easily implement finite state machines (FSMs), states are represented by functions, and events are messages. Not to expand it in detail
4. Timeout setting
The receive syntax in Erlang can add an extra option: timeout, similar to:
receive
Message1 [when Guard1] ->
Actions1 ;
Message2 [when Guard2] ->
Actions2 ;
after
TimeOutExpr ->
ActionsT
end
The TimeOutExpr expression after after returns an integer time (millisecond level), and the accuracy of time depends on Erlang's implementation in the operating system or hardware. If no message is selected within time milliseconds, the timeout setting will take effect, that is, ActionT will be executed. Time has two special values:
1) infinity (infinity), infinity is an atom, and the timeout setting specified will never be executed.
2) 0. If the timeout is set to 0, it means that the timeout setting will be executed immediately, but the system will first try the message in the current "mailbox".
There are several common applications for timeouts, such as how many milliseconds of the current process are suspended:
sleep(Time) ->
receive
after Time ->
true
end.
For example, clear the process's "emailbox" and discard all messages in the "emailbox":
flush_buffer() ->
receive
AnyMessage ->
flush_buffer()
after 0 ->
true
end.
Hang the current process forever:
suspend() ->
receive
after
infinity ->
true
end.
Timeout can also be applied to implementing timers. For example, in the following example, create a process that will send a message to itself after setting the time:
-module(timer).
-export([timeout/2,cancel/1,timer/3]).
timeout(Time, Alarm) ->
spawn(timer, timer, [self(),Time,Alarm]).
cancel(Timer) ->
Timer ! {self(),cancel}.
timer(Pid, Time, Alarm) ->
receive
{Pid,cancel} ->
true
after Time ->
Pid ! Alarm
end.
5. Registration process
In order to send messages to a process, we need to know the process's Pid, but in some cases: there are many global servers in a large system, or the process's Pid needs to be hidden for security reasons. In order to achieve the purpose of sending messages to a process that does not know Pid, we provide a way to register a process and register names for the processes, which must be atoms.
Basic call form:
register(Name, Pid)
Connect Name to Process Pid
unregister(Name)
Cancel the correspondence between Name and the corresponding process.
whereis(Name)
Returns the Pid of the process associated with Name. If no process is associated with it, it returns atom:undefined
registered()
Returns the name list of currently registered processes
6. Process priority
To set the priority of the process, BIFs can be used:
process_flag(priority, Pri)
Pri can be normal or low, and the default is normal
Processes with high priority will execute a little more with relatively low priority.
7. Process group
All ERLANG processes have a Pid associated with a shared group called Group Leader. When a new process is created, it will be added to the same process group. The Group Leader of the original system process is itself, so it is also the Group Leader of all created processes and child processes. This means that Erlang's process is organized into a Tree, and the root node is the first process to be created. The following BIFs are used to manipulate process groups:
group_leader()
Returns the Pid of the Group Leader that executes the process
group_leader(Leader, Pid)
Set the Group Leader of the process Pid as the Leader of the process
The process model is easy to build Client-Server model, There is a section in the book that specifically discusses this point, focusing on the design of interfaces and isolation issues at the abstract level, and will not be translated.