티스토리 뷰
싱글턴(Singleton) 패턴은 객체의 인스턴스가 애플리케이션 내에서 단 하나만 생성되도록 보장하는 디자인 패턴입니다. 이 패턴은 전역 변수를 사용하지 않고 객체에 대한 전역 접근을 제공하며, 동시에 여러 인스턴스의 생성을 방지하여 리소스 사용을 최적화할 수 있습니다.
- 생성자를 비공개로 만들어 클래스 외부에서 인스턴스를 직접 생성할 수 없게 합니다.
- 클래스 내에 정적(private static) 멤버 변수로 자기 자신의 유일한 인스턴스를 저장합니다.
- 공개적인 정적 메서드(getInstance) 를 제공하여 유일한 인스턴스에 접근할 수 있게 합니다. 이 메서드는 내부적으로 인스턴스가 존재하지 않을 경우에만 생성하고, 이미 존재하는 경우에는 기존 인스턴스를 반환합니다.
#include <iostream>
class Singleton {
private:
// 1. 생성자, 복사 생성자, 대입 연산자를 비공개로 선언합니다.
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 2. 유일한 인스턴스를 저장할 정적 멤버 변수를 선언합니다.
static Singleton* instance;
public:
// 3. 유일한 인스턴스에 접근할 수 있는 정적 메서드를 제공합니다.
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
void doSomething() {
// 싱글턴 인스턴스가 할 작업을 정의합니다.
std::cout << "Doing something" << std::endl;
}
};
// 정적 멤버 변수의 초기화
Singleton* Singleton::instance = nullptr;
int main() {
// 싱글턴 인스턴스에 접근하여 메서드를 호출합니다.
Singleton::getInstance()->doSomething();
return 0;
}
C++에서 싱글턴 패턴을 스레드 안전하게 구현하는 방법은 몇 가지가 있습니다. 여기서는 가장 일반적으로 사용되는 몇 가지 방법을 소개하겠습니다.
1. 더블 체킹 록(Double-Checked Locking) 패턴
더블 체킹 록 패턴은 싱글턴 인스턴스가 아직 생성되지 않았을 때만 잠금을 사용하여 인스턴스를 생성하는 방법입니다. 이 방법은 인스턴스가 이미 생성된 후에는 잠금 오버헤드 없이 접근할 수 있어 효율적입니다. 하지만, C++에서는 메모리 모델의 복잡성으로 인해 이 패턴을 올바르게 구현하는 것이 어렵습니다. C++11 이후의 메모리 모델에서는 아래와 같이 std::atomic과 std::call_once를 사용하여 이 패턴을 안전하게 구현할 수 있습니다.
2. std::call_once와 std::once_flag 사용
C++11에서는 스레드 안전한 초기화를 위해 std::call_once와 std::once_flag를 제공합니다. 이 방법을 사용하면 초기화 코드가 단 한 번만 실행되도록 보장되며, 여러 스레드에서 동시에 접근하더라도 안전합니다.
#include <iostream>
#include <mutex>
class Singleton {
public:
static Singleton& getInstance() {
std::call_once(initInstanceFlag, &Singleton::initSingleton);
return *instance;
}
static void initSingleton() {
instance = new Singleton();
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() {}
static Singleton* instance;
static std::once_flag initInstanceFlag;
};
Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::initInstanceFlag;
int main() {
// 다중 스레드 환경에서도 안전하게 싱글턴 인스턴스에 접근
Singleton& singletonInstance = Singleton::getInstance();
return 0;
}
3. static 지역 변수 사용 (Meyers' Singleton)
Scott Meyers에 의해 소개된 이 방법은 C++11 이후 가장 권장되는 방식 중 하나입니다. 함수 내부의 static 지역 변수를 사용하면, 첫 호출 시에만 초기화되고 스레드 안전성이 보장됩니다. C++11 표준에서는 이러한 초기화가 스레드 안전하도록 명시하고 있습니다.
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
- Total
- Today
- Yesterday
- CMake
- 스쿠버다이빙
- 패턴
- PowerShell
- script
- C++
- 성산블루버블
- 블루버블
- 스쿠버 다이빙
- 블루버블다이빙팀
- DLL
- C
- Linux
- OpenSource
- effective
- 블루버블다이브팀
- 암호화
- 울릉도
- C# 고급 기술
- Build
- 외돌개
- Effective c++
- Windows
- 서귀포블루버블
- C#.NET
- 제주도
- 네트워크 정보
- 서귀포
- C#
- 현포다이브
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |