3 클라이언트가 동시에 함수를 호출하면 함수가 카운터를 한 번만 증가시키고 오류가 발생합니다. 어떻게 다른 함수가 끝내고 실행될 때까지 함수가 기다리게합니까?
gen_server
으로 만든 간단한 카운터를 사용하고 디스크의 카운터에만 액세스하십시오. 이처럼 gen_server
을 사용하면 파일 액세스 경쟁 조건이 발생하지 않습니다.
다음은 시작하는 뭔가 :
-module(file_counter).
-export([start_link/0, start/0, increment/0]).
-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
start() ->
gen_server:start({local, ?MODULE}, ?MODULE, [], []).
increment() ->
gen_server:call(?MODULE, increment).
init([]) ->
{ok, "file_counter.txt"}.
handle_call(increment, _From, File) ->
Counter = case file:read_file(File) of
{ok, Binary} -> binary_to_integer(Binary);
{error, enoent} -> 0
end,
ok = file:write_file(File, integer_to_binary(Counter + 1)),
{reply, Counter, File}.
handle_cast(_Req, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
데모 :
이
1> c(file_counter).
{ok,file_counter}
2> file_counter:start_link().
{ok,<0.40.0>}
3> file_counter:increment().
0
4> file_counter:increment().
1
5> file_counter:increment().
2
6> [ spawn_link(file_counter, increment, []) || _ <- lists:seq(1, 9998) ].
[<0.45.0>,<0.46.0>,<0.47.0>,<0.48.0>,<0.49.0>,<0.50.0>,
<0.51.0>,<0.52.0>,<0.53.0>,<0.54.0>,<0.55.0>,<0.56.0>,
<0.57.0>,<0.58.0>,<0.59.0>,<0.60.0>,<0.61.0>,<0.62.0>,
<0.63.0>,<0.64.0>,<0.65.0>,<0.66.0>,<0.67.0>,<0.68.0>,
<0.69.0>,<0.70.0>,<0.71.0>,<0.72.0>,<0.73.0>|...]
7> file_counter:increment().
10001
그냥 각각의 호출을하기 전에 file_counter:increment()
를 호출하고 계수로 반환 된 값을 사용합니다.
편집 : 이것은 제가 작성한 빠른 모듈입니다. start
, start_link
및 init
에 파일 이름을 전달하여 파일 이름을 구성 할 수있을뿐만 아니라 카운터의 여러 복사본을 실행할 수 있도록하려면 프로세스 이름을 등록하지 않아야합니다. 이 코드는 실제로 시작하기위한 POC입니다.
은 (AN SSD 디스크가있는 시스템에서 I 초당
file_counter:increment()
약 5000 회 수행 할 수 있었다.)
더 시동시의 카운터 판독 ETS에 저장하는 것이 효율적 (또는 상태 처리) , 종료시 다시 작성하십시오. 그러나 이것은 100 % 신뢰성이 없습니다. 많은 전화를 잊어 버리고 이전 전화 번호로 전화를 걸면 어떻게됩니까? –
웹 서비스가 어떤 종류의 오류를 반환하고 다음 호출이 의미가 없습니다. 이것이 카운터를 올바르게 유지하는 것이 중요한 이유입니다. –
@Roger Lipscombe –