성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <div style='font-family: 맑은 고딕, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# Singleton 인스턴스 생성</div><br /> <br /> 그러고 보니, Singleton에 대한 글을 몇 개 쓰긴 했군요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > C++에서 싱글톤 구현하기 ; <a target='_tab' href='/2/0/846'>http://www.sysnet.pe.kr/2/0/846</a> DataContext가 thread-safe한 것인가? ; <a target='_tab' href='/2/0/855'>http://www.sysnet.pe.kr/2/0/855</a> </pre> <br /> 위의 2번째 글에 소개한 링크에서 C#에서의 Singleton 개체 생성에 관한 내용을 확인할 수 있는데요.<br /> <br /> C#은 닷넷이 채택한 <a target='tab' href='https://learn.microsoft.com/en-us/archive/msdn-magazine/2012/december/csharp-the-csharp-memory-model-in-theory-and-practice'>메모리 모델</a> 덕분에 단순한 DCLP(Double Checked Locking Pattern) 코딩만으로 singleton 개체가 보장됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > static object lockInstance = new object(); static MyObject myInstance; internal static MyObject Instance { get { if (myInstance == null) { lock (lockInstance) { if (myInstance == null) { myInstance = new MyObject(); } } } return myInstance; } } </pre> <br /> <a target='tab' href='http://www.yes24.com/Product/Goods/15169403'>Jeffrey Richter의 "CLR via C#" 책</a>을 보면 현재의 CLR이 채택한 메모리 모델이 그럴 뿐 별도로 누군가? 또는 향후에 다른 운영체제에 구현될 CLR의 메모리 모델이 다른 경우에는 적절한 Memory Barrier를 사용해야 한다고 씌여져 있습니다. (아마도 Mono에서는 그래야 될지도 모르겠습니다.)<br /> <br /> 역시 "CLR via C#" 책에도 나오지만 대개의 경우 그냥 static 생성자에서 개체를 생성하도록 하는 것이 가장 권장되는 방식이기도 합니다. 저 역시 그렇게 많이 사용하고. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > static MyObject myInstance = new MyObject(); // .NET에서는 너무나 간단한 Singleton 개체 생성 // (유의할 점: <a target='tab' href='https://www.sysnet.pe.kr/2/0/12473'>.NET 런타임에 따라 달라지는 정적 필드의 초기화 유무</a>) </pre> <br /> 그래도 가끔은 DCLP의 "Lazy Initialization"이 그리울 수도 있을 텐데요. 안전한 static 생성자의 구현 방식에 "Lazy Initialization"을 적용시킨 훌륭한 코드가 "<a target='_tab' href='http://www.yoda.arachsys.com/csharp/singleton.html'>Implementing the Singleton Pattern in C#</a>" 글에서 "Fifth version - fully lazy instantiation" 절에 소개되어 있으니 참고하십시오.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그냥 끝내기 아쉬우니, 잠깐 다소 쓸데없을 것 같은 이야기를 붙여본다면!<br /> <br /> 결국 Singleton 인스턴스를 생성하는 데에는, 반드시 해당 타입을 한번이라도 접근을 해줘야 하는 것이 중요합니다. 그래서, 때로는 다음과 같이 일부러 빈 static 함수를 만들어 호출해 줄 때도 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > class MyType { static MyType instance = new MyType(); public static void Initialize() { } } class Program { static void Main(string[] args) { MyType.Initialize(); } } </pre> <br /> 처음에 위와 같이 코드를 작성해 보고 내심 걱정이 되었습니다. 왜냐하면, MyType.Initialize 메서드는 아무런 일도 하지 않기 때문에 DEBUG 빌드의 어셈블리를 실행할 때는 잘 될지 모르지만, RELEASE 빌드의 어셈블리를 실행할 때는 최적화로 인해 메서드 호출이 생략될 수 있기 때문입니다.<br /> <br /> 물론, 테스트를 해보면 결과가 금방 나오는데 MyType 인스턴스는 정상적으로 릴리스 빌드에서도 생성이 됩니다.<br /> <br /> 오호~~~ 그렇다면 static 메서드에 대해서는 (IL 코드가 없어도) JIT 컴파일러가 반드시 호출을 해주는 걸까요?<br /> <br /> 그건 또 아닙니다. 위의 MyType.Initialize는 분명히 JIT 컴파일링 되지 않습니다. (CLR Profiler로 확인해 보면 알 수 있습니다.) 하지만 똑똑한 JIT 컴파일러는 Initialize 호출만 생략할 뿐 해당 타입의 cctor까지는 호출해 줍니다. 즉, (RELEASE 빌드) 실행 시에는 다음과 같은 식으로 동작을 하는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > class Program { static void Main(string[] args) { MyType..cctor(); // 사실 이런 식의 호출이 명시적으로 가능했으면 좋겠습니다. // 쓸데없이 빈 메서드 만들어 줄 필요가 없으니. // 혹은, <a target='tab' href='https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.runtimehelpers.runclassconstructor'>RuntimeHelpers.RunClassConstructor</a>의 힘을 빌려도 되지만 코드가 쓸데없이 어려운 듯한 분위기를 풍깁니다. ^^ } } </pre> <br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
9231
(왼쪽의 숫자를 입력해야 합니다.)