在erlang示例中应用互斥锁

在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

我目前有一个使用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(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