如何在erlang中实现

时间:2016-02-15 15:50:54

标签: erlang

我在考虑使用列表来存储元素(文件)

如何更改下面的代码,以便锁定一个进程(用户)访问一个文件(列表中的元素),同时允许另一个进程(用户)访问该文件。

-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).

-module(banktest).
-export([start/0, client/1]).

start() ->
    bank:start(),
    mutex:start(),
    register(tester_process, self()),
    loop(10, 20, 100),
    unregister(tester_process),
    mutex:stop(),
    bank:stop().

loop(_, _, 0) ->
    true;
loop(Amount1, Amount2, N) ->
    bank:set_bal(0),
    spawn(banktest, client, [Amount1]),
    spawn(banktest, client, [Amount2]),
    receive
        done -> true
    end,
    receive
        done -> true
    end,
    io:format("Expected balance = ~B, actual balance = ~B~n~n",
              [Amount1 + Amount2, bank:get_bal()]),
    loop(Amount1, Amount2, N-1).

client(Amount) ->
    bank:deposit(Amount),
    tester_process ! done.

2 个答案:

答案 0 :(得分:0)

如果要序列化写入调用但允许读取调用,则可以按如下方式更改代码:

account(Balance, WriteLocker) ->
  receive
    free_lock ->
      account(Balance, undefined),
    {set, NewBalance, Caller} when WriteLocker =:= undefined ->
      Caller ! done,
      account(NewBalance, Caller),
    {get, From} ->
      From ! {balance, Balance},
      account(Balance, WriteLocker);
    stop -> ok
  end.

wait() ->
  receive
    {done, WriteLock} -> WriteLock ! free_lock.
  end.

set_bal(B) ->
  account_process ! {set, B, self()},
  wait().

如果您也想锁定阅读器,请将警卫添加到{get, From}消息。

答案 1 :(得分:0)

好的,仍然不太明白这个问题,但我会尝试澄清,然后提出一个解决方案:

  1. 您希望管理对一组文件而非银行帐户的访问权限
  2. 您希望一个用户具有对文件的写入权限,而其他用户仍具有对该文件的读取权限
  3. 如果这是您想要的,那么您可以简单地将每个文件视为银行帐户。这意味着您应该为每个文件启动一个进程(类似于bank模块中的代码)。换句话说:

    • 1个银行帐户,您需要1个流程
    • 3个银行账户,您需要3个流程
    • 10个文件,您需要10个流程

    实施细节取决于您计划如何管理服务器上的文件,但在简单的场景中,该过程可以类似于现有代码:

    file(FileName) ->
        receive
            {write, From, Data} ->
                ok = file:write_file(FileName, Data),
                From ! ok,
                file(FileName);
            {read, From} ->
                {ok, Data} = file:read_file(FileName), 
                From ! Data,
                file(FileName);
            stop -> ok
        end.
    
    start() ->
        File_PID = spawn(file, file, ["somefile.txt"]),
        register(file_process, File_PID).