이 녀석도 그렇게 대단한 놈은 아니지만, 멀티 스레드 환경에서 Singleton 을 사용하는 경우라면 꼭 기억해 둘 필요가 있겠다. 내 경우 Delphi 에서 보통 다음처럼 Singleton 을 작성한다.
TSingleton = class
protected
class var Instance: TSingleton;
constructor Create;
destructor Destroy; override;
public
class function GetInstance: TSingleton;
class procedure ReleaseInstance;
end;
{ TSingleton }
constructor TSingleton.Create;
begin
inherited;
end;
destructor TSingleton.Destroy;
begin
inherited;
end;
class function TSingleton.GetInstance: TSingleton;
begin
if not Assigned(Instance) then
begin
if not Assigned(Instance) then Instance := Create;
end;
Result := Instance;
end;
class procedure TSingleton.ReleaseInstance;
begin
if Assigned(Instance) then FreeAndNil(Instance);
end;
이때 GetInstance 를 호출하는 시점을 디어셈블해보면 다음과 같다.
파스칼로 한 줄이라도 CPU 기준으로 봤을때 인스트럭션이 여러개 발생한다. 문제는 스레드의 컨텍스트 스위칭이 인스트럭션 단위로 발생하는데 있다. 즉, 최초 인스턴스의 존재 여부를 확인 후, 생성하는 과정에서 스레드간 경쟁(race condition)에 의하여 복수개의 인스턴스가 생성될 수 있는 잠재적 위험요소가 있는 것이다. 여기서 Scoped Locking 을 사용하여 동기화한다고 해보자.
class function TSingleton.GetInstance: TSingleton;
var
Guard: TGuard;
begin
if not Assigned(Instance) then
begin
Guard := TGuard.Create(Cri);
try
Instance := Create;
finally
Guard.Free;
end;
end;
Result := Instance;
end;
해당 부분을 디어셈블해보면 다음과 같다.
이 경우도 문제가 발생할 수 있는데, 스레드간 race condition 으로 Instance 의 할당 여부를 검사하는 부분을 복수개의 스레드가 통과할 수 있기 때문이다. 이 후, TGuard 에 의해 Scoped Locking 이 걸린다고 하여도 해당 검사 부분을 통과한 스레드는 이 후 순차적으로 인스턴스를 생성하게 된다. 따라서, 이러한 문제점까지 해결하려면 Locking 이 된 이후에 한번 더 Instance 의 생성 여부를 검사해주어야하는 것이다.
class function TSingleton.GetInstance: TSingleton;
var
Guard: TGuard;
begin
if not Assigned(Instance) then
begin
Guard := TGuard.Create(Cri);
try
if not Assigned(Instance) then Instance := Create;
finally
Guard.Free;
end;
end;
Result := Instance;
end;
이렇게 두 번 검사한다고 하여 Double-Checked Locking 이라고 부른다.
반응형
'개발일지 > 아키텍트' 카테고리의 다른 글
Delphi 투게더의 Observer 패턴 소스 오류 (0) | 2012.04.19 |
---|---|
POSA2, Scoped Locking, Strategized Locking 패턴 (0) | 2012.04.05 |
Proactor with EPOLL, SELECT (2) | 2012.03.15 |
Delphi 에서 Leader-Follower 패턴 구현 (0) | 2012.03.14 |
FPC 에서 Leader-Follower 패턴 구현 (0) | 2012.03.09 |
댓글