我在考虑使用列表来存储元素(文件)
如何更改下面的代码,以便锁定一个进程(用户)访问一个文件(列表中的元素),同时允许另一个进程(用户)访问该文件。
-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.
答案 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)
好的,仍然不太明白这个问题,但我会尝试澄清,然后提出一个解决方案:
如果这是您想要的,那么您可以简单地将每个文件视为银行帐户。这意味着您应该为每个文件启动一个进程(类似于bank模块中的代码)。换句话说:
实施细节取决于您计划如何管理服务器上的文件,但在简单的场景中,该过程可以类似于现有代码:
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).