이 포스트의 목적

  • 싱글턴이 쓰레드와 만났을 경우 고려사항을 남기기 위해서이다.

이 포스트의 준비물

  • Firefox 4.0 b7
  • g++ 4.3.2
  • vim
  • putty

참조 링크

참조 서적

  • 안드레 알렉산드레스쿠 저. Modern C++ Design. 이기형 역.
    Addiston-Wesley. 인포북. 초판 2003.07.30. page(244 ~ 248)
내용

싱글턴이 쓰레드와 만났을 경우, 고려해야할 사항은 무엇인가?

  • 싱글턴 객체의 생성 동기화

여러 쓰레드가 동시에 싱글턴 객체를 생성할 경우, 마지막에 생성된 싱글턴 객체만 정상적으로 사용할 수 있고, 그 전에 생성된 객체는 사용할 수 있게 되므로, 싱글턴 객체를 생성할 때, 쓰레드에 안전하도록 유의해야 한다.

동기화 방법으로는 임계영역 객체(뮤텍스, 세마포어 등)를 이용한 동기화 방법이 있다. 하지만 싱글턴 객체를 사용할 때마다 동기화 객체를 이용한 방법은 성능상 큰 문제를 발생 시키므로, "이중 검사 동기화(double-checked locking) 패턴"을 사용하여, 이 문제들을 해결할 수 있고, 그 코드는 다음과 같다.

이 방법으로 쓰레드 문제도 피해가고, 성능 문제도 피해갈 수 있다. 하지만 여기에도 문제가 있다.

문제점

  • p_instance가 A 쓰레드에서 초기화된 메모리지만, B 쓰레드 입장에선 아직 초기화 되지 않은 변수로 보일 수 있는 문제

이 문제는 특정 시스템에서 발생하는 것으로 알려졌는데(어느 환경인지는 설명이 없다. 왜 이 중요한 정보가 없을까?), 이 문제를 풀기 위해서 두가지 방법이 존재한다.

  • 언어적 해결 방법 - C++ 에서 지원하는 volatile 키워드 p_instance에 적용한다.
  • 구조적 해결 방법 - 메인 쓰레드에서 먼저 싱글턴 객체를 생성한 뒤, 다른 쓰레드에서 사용한다.

구조적 해결 방법이 가장 확실하지만, 구조를 바꾸기는 힘들기 때문에, 언어적 해결 방법을 많이 쓰일 것이다. 하지만 이 언어적 해결 방법에도 문제가 있다.

언어적 해결 방법의 문제점

  • volatile 키워드는 컴파일러마다 그 구현이 달라, 메모리 장벽(memory barrier)을 보장하지 않는다. 또는 보장한다.

이렇기 때문에, ... 알아서들 자신의 환경과 volatile 키워드를 조사하여 사용하는게 맞을것 같다.

여담

  • 많은 경우 문제란 환경에 따라 달라지는 것을 알 수 있다.
  • g++ 에선 volatile 키워드가 어떤지 살펴봐야 겠다.
  • 싱글턴에서 이중 검사 동기화 패턴이 안먹히는 경우가 생길수 있을지 의문이다.(이론적으로 생긴다 하더라도...)

  • 다음 항목에선 마의 장벽, 싱글턴 패턴을 단위 전략(또는 정책 기반 - policy-based)으로 구성시키는 방법을 다룬다.

:wp

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기