성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Reordering on an Alpha processor ;...
[정성태] 공유 감사합니다. ^^ 참고로, WPF에서 WindowsF...
[Tom Lee] 답변 감사합니다. 나름의 해결책 연구해보고 여기에도 공유해봅니다...
[정성태] 아래의 글을 보면, MoveWindow 하면 될 듯한데요. ^^...
[Tom Lee] 안녕하세요 올려주신 글 참고하여 WPF 어플리케이션 안에 Uni...
[정성태] A graphical depiction of the steps ...
[정성태] 질문을 주셔서 출판사 측에 문의를 했습니다. 약 한 달 정도 후...
[Thorondor
] @정성태 개인 블로그인데도 거의 커뮤니티 급 인 것 같아요. 요...
[정성태] Roll A Lisp In C - Reading ; https...
[정성태] Java - How to use the Foreign Funct...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <br /> <div class='mainCenterTitle'>ManagedThreadId - 두 번째 이야기</div><br /> <br /> [이 토픽은 이전 "<a target='_tab' href='/2/0/491'>ManagedThreadId ?</a>" 글에 달린 댓글에 대해 답변으로 쓴 것입니다.]<br /> <br /> 물론, ManagedThreadId가 Thread.GetHashCode의 래퍼에 불과하긴 하지만. 관리 스레드와 Native 스레드를 구분해야 하는 이유가 Fiber의 도입 여부에 의존한다는 것은 간과할 수 없는 사실로 보입니다. 실제로 Obsolete에 나온 경고문이나, MSDN 도움말에 나온 ManagedThreadId의 설명을 보아도 그렇습니다.<br /> <br /> <pre class='code'> .NET Framework Class Library - Thread.ManagedThreadId Property ; <a target='_tab' href='https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.managedthreadid'>https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.managedthreadid</a> The value of the ManagedThreadId property does not vary over time, even if unmanaged code <b>that hosts the common language runtime implements the thread as a fiber.</b> </pre> <br /> 말씀하신 내용 중에, <br /> <br /> <span class='comment'> "<br /> 굳이 Fiber를 운운하지 않더라도 호스팅 환경에 따라 <b>서로 다른 두 개 이상의 운영체제 스레드가 하나의 Thread 객체에 매핑</b>될 수 있기 때문입니다.<br /> "</span><br /><br /> <br /> 위와 같이 언급하신 것이 있는데, 제 생각에는 .NET 1.x의 그 문서 내용을 너무 확장해서 판단하신 것이 아닌가 생각됩니다. 현실적으로 볼 때 "서로 다른 두 개 이상의 운영체제 스레드가 하나의 .NET Thread 객체에 매핑"되는 것은 불가능하기 때문입니다. 만약, 그러한 매핑이 가능하다면 (ThreadStatic 특성이 적용된 것을 포함해서) 여전히 PInvoke로 호출되는 하부 자원들에서 사용되고 있을지도 모르는 TLS는 어떻게 관리가 되는 것인지요?<br /> <br /> ICLRTask, ICLRTaskManager 등의 인터페이스가 없는 .NET 1.x에서는 그러한 호스팅을 구현하는 것이 불가능했으며, .NET 2.0에 와서야 그러한 인터페이스가 구현되어 CLR 호스팅을 커스터마이징할 수 있는 기회가 생기긴 했지만, 그조차도 TLS를 사용하는 부분에 대해서 FLS(Fiber local storage)를 사용하도록 바꿔주는 구현이 필요했는데, .NET 1.x에서는 FLS 관련한 코드가 전혀 없기 때문에 "향후의 CLR 버전의 가능성"이 그랬을 뿐, 실제로 1.x에서 가능했던 것은 아닙니다. 그리고, .NET 2.0을 기반으로 한 SQLClr에서 실제로 그러한 구현을 시도했지만, 잘 아시는 것처럼 실제 릴리스 버전에서는 제외되었고요.<br /> <br /> 설령 FLS를 쓴다고 해도 Fiber 자체가 thread-affinity이기 때문에 서로 다른 Native 스레드에서 접근할 수 있는 배려가 전혀 안 되어 있습니다. <br /> <br /> <hr style='width: 50%' /><br /> <br /> 그다음... ^^ 아래의 의견에 대해서 말씀드리면,<br /> <br /> <span class='comment'> "<br /> 1.x 시절부터 닷넷 환경에서 운영체제의 thread id는 <b>신뢰할 수 없는 값</b>이였습니다.<br /> "<br /> </span><br /><br /> <br /> Fiber 구현 여부를 제외한다면, .NET 1.x/2.0에서 GetCurrentThreadId와 Thread.GetHashCode를 구분할 필요는 없다고 보입니다. 즉, 여전히 신뢰할 수 있는 값입니다. 그렇지 않다면 Obsolete 수준이 아니라 아예 사용할 수 없도록 만들어야 했습니다.<br /> <br /> 좀 더 자세하게 살펴본다면, 해당 논리 스레드(.NET Managed Thread)가 일단 생성된 이후부터는 철저하게 하나의 동일한 Native 스레드에 매핑되어집니다. 위에서 이미 강조해서 말씀드렸지만, TLS를 사용하는 여러 기반 환경으로 인해 관리 스레드를 여러 개의 Native 스레드에서 스케줄링하는 것은 불가능합니다.<br /> <br /> 하나의 관리 스레드가 생성되어 그 ID가 3이고, 이때 Native 스레드 ID는 3000이었다고 가정해 보겠습니다. .NET 1.x는 물론이고, 2.0 현재의 버전에서도 TLS로 인해 절대로 관리 스레드(3)를 수행하는 도중, (Suspend 후 Resume을 포함해서) Native 스레드의 ID가 3000 이외의 값이 나오는 경우는 없습니다.<br /> <br /> 나아가서, 관리 스레드가 종료된 후 GC까지 구동되어 완전하게 관리 스레드 자원이 해제된 경우에는 새로 생성되는 관리 스레드에 대해서 이전의 관리 스레드 ID 3의 경우 및 Native 스레드 ID 3000이 나오는 것이 가능합니다. 결국 스레드가 종료된 이후에는 관리 스레드 ID나 Native Thread ID나 모두 해당 숫자가 재사용된다는 것에는 변함이 없습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 현재까지는, 순전히 Fiber의 도입 문제로 인해 ManagedThreadId가 필요한 것을 알 수 있습니다. 하나의 Native 스레드에서 여러 개의 Fiber가 묶여지다 보니, 각각의 Fiber에서 스케줄링 되는 관리 스레드들이 자신의 고유 스레드 ID가 필요하게 되었고, 그런 이유로 인해 .NET에서 ManagedThreadId가 제공되는 것이 의미가 있게 되는 것입니다. 물론... Fiber가 없다면, ManagedThreadId를 쓰나 GetCurrentThreadId를 쓰나 해당 스레드를 구분하는 고유 ID로써 사용하는 것에는 무리가 없고요.<br /> <br /> 이러저러한 이야기를 종합할 때. 단순히 1.x의 Thread.GetHashCode가 Thread.ManagedThreadId로 온 것에 불과하지만, 실제 뒷 이야기는 Fiber와 관련되어 있다는 것을 "<a target='_tab' href='/2/0/491'>ManagedThreadId ?</a>" 토픽에서 써본 것이었습니다. <br /> <br /> 그 외, Fiber와 관련된 블로그 토픽을 조금 소개해 봅니다.<br /> <br /> <pre class='code'> Fibers and the CLR ; <a target='tab' href='https://joeduffyblog.com/2006/11/09/fibers-and-the-clr/'>https://joeduffyblog.com/2006/11/09/fibers-and-the-clr/</a> ; http://www.bluebytesoftware.com/blog/CommentView,guid,2d0038b5-7ba5-421f-860b-d9282a1211d3.aspx AppDomain.GetCurrentThreadId() and ManagedThreadId are different ; <a target='_tab' href='http://www.thescripts.com/forum/thread440146.html'>http://www.thescripts.com/forum/thread440146.html</a> How to get thread id for a managed thread? ; <a target='_tab' href='https://learn.microsoft.com/en-us/archive/blogs/junfeng/how-to-get-thread-id-for-a-managed-thread'>https://learn.microsoft.com/en-us/archive/blogs/junfeng/how-to-get-thread-id-for-a-managed-thread</a> </pre> <br /> 참고로, 관리 스레드가 여전히 TLS 등의 문제로 인해 발생할 수 있는 문제점을 해결하기 위해 다음과 같은 함수들이 ManagedThreadId와 함께 .NET 2.0에 추가되었고요. (물론, 현재는 이런 함수들의 호출 여부가 전혀 영향을 주지 않고 있지만.)<br /> <br /> <pre class='code'> Thread.BeginThreadAffinity Method ; <a target='_tab' href='https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.beginthreadaffinity'>https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.beginthreadaffinity</a> Thread.EndThreadAffinity Method ; <a target='_tab' href='https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.endthreadaffinity'>https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.endthreadaffinity</a> </pre> <br /> 제 생각이 틀렸나요??? <br /> 의견을 부탁드립니다. ^^ 말씀하신 것처럼, 좋은 토론이 되지 않나 싶습니다.<br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8212
(왼쪽의 숫자를 입력해야 합니다.)