一个actor一次处理一个消息并封装它不共享的状态这一事实足以提供同步语义。因此,互斥(写锁定)得到了解决。但是,我们如何实现读写锁语义,其中多个读者可以并行工作,但读者和作者是互斥的?例如:并发HashMap。
通过消息传递,“模拟”锁定的actor可以使用正确的权限处理写入/读取访问模式。这个想法是其他演员发送请求以获取锁定演员的锁定,并等待回复。使用Erlang,锁定actor的状态可以像#{writer := boolean(), readers := integer()}
和控制循环类似:
%% A writer holds the lock:
loop(#{writer := true, readers := 0}) ->
receive
unlock_write -> loop(#{writer => false, readers => 0})
end;
%% One or more readers hold the lock:
loop(#{writer := false, readers := N}) when N > 0 ->
receive
{lock_read, Who} -> Who ! lock_granted, loop(#{writer => false, readers => N + 1});
unlock_read -> loop(#{writer => false, readers => N - 1})
end;
%% No writer or readers hold the lock:
loop(#{writer := false, readers := 0}) ->
receive
{lock_read, Who} -> Who ! lock_granted, loop(#{writer => false, readers => 1});
{lock_write, Who} -> Who ! lock_granted, loop(#{writer => true, readers => 0})
end.
请注意,在每个状态下,可以处理的唯一消息是该状态允许的消息(例如,当写入程序保持锁定时,只能处理unlock_write
消息并更改状态)。
在Erlang中,您可以通过几种方式实现此目的。最明显的方法是使用ETS表。所有ets写入都是原子的(即使它们包含多个记录)可能更好的是设置一个受保护的ets表,其中1个进程可以写入但所有进程都可以读取。
演员模型解决方案中的相互上下文按队列概念处理,并避免处理背压的锁定机制。如果你想要碎片记忆使用其他东西,如ets。
使用gen_server。哈希映射可以在状态中保留。您可能具有在状态(hashmap)上运行的函数。