在erlang示例中应用互斥锁
我目前有一个使用erlang编写的简单银行帐户,我希望在其中添加一个互斥体,以便在设置/获取余额可能被中断的情况下无法进行两次存款,从而导致最终值错误,例如bal a=10 bal B=20:在erlang示例中应用互斥锁,erlang,mutex,Erlang,Mutex,我目前有一个使用erlang编写的简单银行帐户,我希望在其中添加一个互斥体,以便在设置/获取余额可能被中断的情况下无法进行两次存款,从而导致最终值错误,例如bal a=10 bal B=20: WRONG get_bal.A 0 → get_bal.B 0 → set_bal.A 10 → set_bal.B 20 == 20 RIGHT get_bal.A 0 → set_bal.A 10 → get_bal.B 10 → set_bal.B 30 == 30 我的代码如下: -module
WRONG
get_bal.A 0 → get_bal.B 0 → set_bal.A 10 → set_bal.B 20 == 20
RIGHT
get_bal.A 0 → set_bal.A 10 → get_bal.B 10 → set_bal.B 30 == 30
我的代码如下:
-module(bank).
-export([account/1, start/0, stop/0, deposit/1, get_bal/0, set_bal/1]).
account(Balance) ->
receive
{set, NewBalance} ->
account(NewBalance);
{get, From} ->
From ! {balance, Balance},
account(Balance);
stop -> ok
end.
start() ->
Account_PID = spawn(bank, account, [0]),
register(account_process, Account_PID).
stop() ->
account_process ! stop,
unregister(account_process).
set_bal(B) ->
account_process ! {set, B}.
get_bal() ->
account_process ! {get, self()},
receive
{balance, B} -> B
end.
deposit(Amount) ->
OldBalance = get_bal(),
NewBalance = OldBalance + Amount,
set_bal(NewBalance).
我想知道是否有人可以用简短的注释来实现互斥,以解释您的思维过程。这将是一个巨大的帮助!再次感谢如果您正确使用,帐户流程的消息队列可以提供您想要的效果。例如,您的
存款/1
函数有问题,因为它执行读-修改-写操作,其中读和写是两个独立的操作。因为它们是分开的,所以它们允许其他不相关的操作在它们之间溜进,破坏您在帐户之外执行的计算
account(Balance) ->
receive
{deposit, Amount, From} ->
NewBalance = Balance + Amount,
From ! {deposit, Amount, NewBalance},
account(NewBalance);
{withdraw, Amount, From} when Amount > Balance ->
From ! {error, {insufficient_funds, Amount, Balance}},
account(Balance);
{withdraw, Amount, From} ->
NewBalance = Balance - Amount,
From ! {withdrawal, Amount, NewBalance},
account(NewBalance);
{get, From} ->
From ! {balance, Balance},
account(Balance);
stop -> ok
end.
为什么不让账户自己计算呢?毕竟,账户持有资金,因此在账户之外进行账户计算是没有意义的
account(Balance) ->
receive
{deposit, Amount, From} ->
NewBalance = Balance + Amount,
From ! {deposit, Amount, NewBalance},
account(NewBalance);
{withdraw, Amount, From} when Amount > Balance ->
From ! {error, {insufficient_funds, Amount, Balance}},
account(Balance);
{withdraw, Amount, From} ->
NewBalance = Balance - Amount,
From ! {withdrawal, Amount, NewBalance},
account(NewBalance);
{get, From} ->
From ! {balance, Balance},
account(Balance);
stop -> ok
end.
使用这种方法,存款/1
只是以原子方式添加资金并返回新余额:
deposit(Amount) when Amount > 0 ->
account_process ! {deposit, Amount, self()},
receive
{deposit, Amount, NewBalance} ->
{ok, NewBalance}
end.
类似地,draw/1
只要在可能的情况下以原子方式减去资金,返回新余额,或者如果发生透支,则返回错误:
withdraw(Amount) when Amount > 0 ->
account_process ! {withdraw, Amount, self()},
receive
{withdrawal, Amount, NewBalance} ->
{ok, NewBalance};
Error ->
Error
end.
get_bal/0
功能保持不变
使用这种方法,所有事务都是原子的。还有其他方法来测试此问题是否得到解决,例如,测试我以前的代码将返回错误,测试您的重写将返回pass