Microsoft MVP성태의 닷넷 이야기
.NET Framework: 88. ManagedThreadId ? [링크 복사], [링크+제목 복사],
조회: 19734
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 2개 있습니다.)
.NET Framework: 88. ManagedThreadId ?
; https://www.sysnet.pe.kr/2/0/491

.NET Framework: 89. ManagedThreadId - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/492





ManagedThreadId ?


미리 말씀드리자면, 이번 토픽은 아래의 토픽에 대한 부연 설명 차원에서 쓰는 것입니다.

스레드(thread)의 시작 
; http://www.bangsil.pe.kr/board/read.aspx?BoardId=da05ba1b-3e9b-4d16-b8f8-ff2e4f7514c5&PostId=1cc5b053-77a3-46cb-8cdf-345b04e214d7

개인적으로, 가끔 다른 분들이 쓴 이야기를 이렇게 이어서 쓰는 경우가 있는데요. 어차피 저도 그에 대한 토픽을 쓰려면 참조한 해당 토픽을 쓴 분과 비슷한 양의 글을 써야 하거나, 아니면, 해당 토픽의 댓글로 달아둘 수도 있겠는데, 그런 경우에는 애써 쓴 이야기가 댓글 수준으로 묻히는 것이 아깝기 때문에. ^^

그런 저런 이유로 이렇게 릴레이 토픽을 쓰는 것이니 감안해 주십시오. ^^




제가 부연 설명할 것은, 위의 토픽 중간에 나온 다음의 이야기입니다.

(2022-04-07 업데이트: 아래의 글은 닷넷 프레임워크 환경에서만 유효하고, .NET Core/5+에서는 ManagedThreadId와 AppDomain.GetCurrentThreadId의 값이 같습니다. 참고 - 닷넷 런타임에 따라 달라지는 AppDomain.GetCurrentThreadId의 반환값)

Thread.CurrentThread.ManagedThreadIdAppDomain.GetCurrentThreadId()의 값이 다른 이유는 이렇다.

전자의 경우 .NET 2.0에서 새로 생긴 프로퍼티인데 이는 관리되는 스레드의 고유한 아이디가 항상 변하는 점을 보완한 프로퍼티이다.
위 코드를 몇 번이고 컴파일 해 보라.
위의 결과값에서 1과 3이라는 숫자는 바뀌지 않으며 1304와 3132는 항상 바뀔 것이다.

고로 후자의 메서드는 이제 더 이상 사용하지 않는다.

[ObsoleteAttribute("AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads).
To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread.
http://go.microsoft.com/fwlink/?linkid=14202", false)]
public static int GetCurrentThreadId ()



원 글을 쓰신 분이 설명한 대로, 일단 "값이 다른 것"은 맞지만 이유에 대한 설명은 좀 안 맞는 것 같습니다. ^^




잘 알려지지 않았지만, CLR은 상당한 유연성을 갖고 설계되었습니다. 2.0에 와서는 더더욱 그러한 설계가 반영이 되어서 호스팅 환경을 자유롭게 구성할 수 있도록 하고 있습니다. 이쯤에서... 감을 잡으신 분이 계실래나? ^^

그렇습니다. CLR 호스팅의 유연성은 스레드 사용에 대한 사용자 정의도 가능하게 하고 있습니다. 따라서, 호스팅 코드를 어떻게 만드느냐에 따라서, .NET 응용 프로그램의 "논리적인" 스레드 사용이 실제 물리적인 Native 스레드와 1:1 매핑이 될 수도 있고, 아니면 Native 스레드 위에서 사용자 정의되는 경량화된 스레드(Fiber)와 매핑이 될 수도 있습니다. 오호... 답이 나왔습니다. ^^

Fiber와 .NET Managed Thread가 매핑이 되는 경우, Native 스레드의 ID를 반환하는 AppDomain.GetCurrentThreadId 메서드를 사용하게 되면, 서로 다른 Managed Thread 임에도 불구하고 동일한 값을 반환하게 되기 때문에 문제의 소지가 있습니다. 따라서, 그런 경우를 위해 고안된 것이 바로 "Managed Thread ID"입니다.

그렇다면... 과연 Fiber로 Managed Thread가 구현된 호스팅 환경이 구현된 예가 있을까요?

다행히도(?) 아직은 없습니다. 있을 뻔한 적은 있었습니다. 과거 SQL Server 2005에 사용될 SQLClr 호스팅 환경에서 최대한의 성능 개선을 위해 Fiber가 고려된 적이 있었습니다. 고려 수준이 아니라, 실제로 구현이 진행되기도 했습니다. 관련해서는 다음의 토픽에서 그 구현을 엿볼 수 있습니다.

Cooperative Fiber Mode Sample - Day 11  
; https://learn.microsoft.com/en-us/archive/blogs/dinoviehland/cooperative-fiber-mode-sample-day-11

하지만, 곧 이 기능은 RTM 즈음에서 취소되었습니다.

Fiber mode gone for SQLCLR
; https://roberthurlbut.com/blog/fiber-mode-gone-for-sqlclr




현재 여러 제품에서 호스팅 되고 있는 (Internet Explorer, SQL Server, .NET App 등...) CLR 중에는 Fiber를 사용하는 CLR 호스팅은 존재하지 않습니다. 하지만, Microsoft가 GetCurrentThreadId를 "Obsolete" 특성을 준 데에는 향후에 나올 어느 환경에 대한 CLR 호스팅 환경에는 Fiber를 도입할 수도 있음을 시사하기 때문에 만약 여러분들이 GetCurrentThreadId를 사용했다면 다른 CLR 호스팅 환경으로 갈 때 주의해야 할 필요가 있습니다.

어쩌면, 지금도 어느 3rd-party에서인가는, 자신들이 만드는 특수한 응용 프로그램을 위해서 CLR 호스팅 환경을 커스터마이징 하고 있을 지도 모르겠습니다. 물론... 여러분도 Fiber를 쓰는 CLR 호스팅 환경을 제작할 수 있음은 당연하고. ^^



[내용 추가: 2007-05-30]
예전 MSDN Magazine의 특정 칼럼에 대한 질문을 한 번 해서 답변을 받았던 적이 있는 John Robbins에게 "관리 스레드"와 "OS 스레드"에 관한 의견을 좀 구했는데,,, 다음과 같이 메일이 왔습니다. (물론, CLR Team에게 물어보는 것이 가장 확실했겠지만.)

What follows is simply my understanding of how threads work in the CLR environment. Microsoft developers on the CLR team are the ones who can give you the real answer.

Today in Microsoft's CLR implementation, a .NET thread maps directly to a native thread. Thus, the OS thread id is unique per .NET thread. My understanding is that the CLR team didn't want people to rely on that implementation staying consistent forever. Consequently, Microsoft has always said not to assume that because they could change the threading model in the future. The Windows thread scheduler is a great piece of code and has been tuned and tested extensively for twenty years. While you can use fibers, which were put in the OS to assist with porting applications from UNIX that implemented their own threading packages, you're required to implement all the scheduling on your own. My
*opinion* (and only my opinion so don't take this as any official statement from Microsoft) is that to go off and implement your own thread scheduler would be a huge wasted effort so the CLR team will continue to map managed threads to native threads. You're comments about using TLS and the windows API are correct. Again, moving to a fibers implementation would require the CLR to hook many API functions to ensure they work. That would be very easy to mess up and introduce numerous compatibility problems.

There's my opinion.




[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 11/10/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2007-05-23 12시26분
[WaterStone] 내일 정도에 Managed Threaded에 관련된 글을 적겠습니다.
미리 얘기 하자면, 성태씨 생각과는 좀 다른 저의 생각인데요... (기대하시라)
좋은 토론이 되지 않나 싶네요... ^^
[guest]
2007-05-23 12시47분
[WaterStone] 토픽을 쓰려다가... 귀차니즘에...
걍 여기에다 적으면... ManagedThreadId는 별 것 없이 Thread.GetHashCode와 동등한 값이고,
1.x 시절부터 닷넷 환경에서 운영체제의 thread id는 신뢰할 수 없는 값이였습니다.
1.x 문서에도 Thread.GetHashCode가 managed 환경에서 신뢰할 수 있는 쓰레드의 고유 id 였다는 것이지요.
굳이 Fiber를 운운하지 않더라도 호스팅 환경에 따라서 서로 다른 두개 이상의 운영체제 쓰레드가
하나의 Thread 객체에 매핑 될 수 있기 때문입니다.
이러한 사항은 1.x 시절부터 충분히 가능한 상황이였다는 것이지요.
운영체제의 Thread id를 개발자들이 신뢰하지 못하도록 하기 위해(논리적인 닷넷 쓰레드의 명확성을 위해)
기존 AppDomain.GetCurrentThreadId 메쏘드를 Obsolete로 만들어 버리고
GetHashCode 메쏘드 대신 명시적인 속성으로 ManagedThreadId 속성을 추가한 것으로 알고 있습니다.

두개 이상의 운영체제 쓰레드가 하나의 Thread 객체에 매핑 될 수 있는 환경은
말씀하신대로 unmanaged 호스트가 자신이 구성하는 운영체제 쓰레드 풀을 가지고 있고
이 쓰레드 풀을 사용하여 managed 코드를 수행하면 두개 이상의 운영체제 쓰레드가
하나의 닷넷 Thread 객체에 매핑이 될 수 있는 거죠.
제 생각이 틀렸나요?
의견 부탁드립니다... ^^
[guest]
2007-05-28 07시29분
[이방은] 오..이제서야 봤네요..
글 잘읽었습니다..ㅋㅋ
게다가 경상님 글도..기대가..
언능 보러 가야지..쓰셨나..
[guest]
2007-05-28 07시46분
[이방은] 아..귀차니즘 때문에 안쓰셨다고 하셨군요..쿨럭..
확실히..스레드는 참 어려운 분야인듯합니다.
관련 서적도 터무니 없이 부족하고..
강좌 또한 마찬가지지요..
저 또한 기본적인 수준이라 이런 오류를 냈었네요..ㅋ~
그럼에도 불구하고 이런 껀수가 생긴다는 건 참 반가운 일이 아닐수 없습니다..@.@
앞으로도 기대많이 하겠습니다..음트트트...

저의 구라를 막아 주시길..히히~~~
[guest]

... 16  17  18  19  [20]  21  22  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
13141정성태10/17/20227025.NET Framework: 2058. [in,out] 배열을 C#에서 C/C++로 넘기는 방법 - 세 번째 이야기파일 다운로드1
13140정성태10/11/20226339C/C++: 159. C/C++ - 리눅스 환경에서 u16string 문자열을 출력하는 방법 [2]
13139정성태10/9/20226131.NET Framework: 2057. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프로부터 모든 닷넷 모듈을 추출하는 방법파일 다운로드1
13138정성태10/8/20227460.NET Framework: 2056. C# - await 비동기 호출을 기대한 메서드가 동기로 호출되었을 때의 부작용 [1]
13137정성태10/8/20225812.NET Framework: 2055. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프로부터 닷넷 모듈을 추출하는 방법
13136정성태10/7/20226378.NET Framework: 2054. .NET Core/5+ SDK 설치 없이 dotnet-dump 사용하는 방법
13135정성태10/5/20226644.NET Framework: 2053. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프를 분석하는 방법 - 두 번째 이야기
13134정성태10/4/20225361오류 유형: 820. There is a problem with AMD Radeon RX 5600 XT device. For more information, search for 'graphics device driver error code 31'
13133정성태10/4/20225704Windows: 211. Windows - (commit이 아닌) reserved 메모리 사용량 확인 방법 [1]
13132정성태10/3/20225622스크립트: 42. 파이썬 - latexify-py 패키지 소개 - 함수를 mathjax 식으로 표현
13131정성태10/3/20228378.NET Framework: 2052. C# - Windows Forms의 데이터 바인딩 지원(DataBinding, DataSource) [2]파일 다운로드1
13130정성태9/28/20225307.NET Framework: 2051. .NET Core/5+ - 에러 로깅을 위한 Middleware가 동작하지 않는 경우파일 다운로드1
13129정성태9/27/20225652.NET Framework: 2050. .NET Core를 IIS에서 호스팅하는 경우 .NET Framework CLR이 함께 로드되는 환경
13128정성태9/23/20228281C/C++: 158. Visual C++ - IDL 구문 중 "unsigned long"을 인식하지 못하는 #import파일 다운로드1
13127정성태9/22/20226776Windows: 210. WSL에 systemd 도입
13126정성태9/15/20227375.NET Framework: 2049. C# 11 - 정적 메서드에 대한 delegate 처리 시 cache 적용
13125정성태9/14/20227578.NET Framework: 2048. C# 11 - 구조체 필드의 자동 초기화(auto-default structs)
13124정성태9/13/20227347.NET Framework: 2047. Golang, Python, C#에서의 CRC32 사용
13123정성태9/8/20227762.NET Framework: 2046. C# 11 - 멤버(속성/필드)에 지정할 수 있는 required 예약어 추가
13122정성태8/26/20227668.NET Framework: 2045. C# 11 - 메서드 매개 변수에 대한 nameof 지원
13121정성태8/23/20225564C/C++: 157. Golang - 구조체의 slice 필드를 Reflection을 이용해 변경하는 방법
13120정성태8/19/20227128Windows: 209. Windows NT Service에서 UI를 다루는 방법 [3]
13119정성태8/18/20226685.NET Framework: 2044. .NET Core/5+ 프로젝트에서 참조 DLL이 보관된 공통 디렉터리를 지정하는 방법
13118정성태8/18/20225520.NET Framework: 2043. WPF Color의 기본 색 영역은 (sRGB가 아닌) scRGB [2]
13117정성태8/17/20227734.NET Framework: 2042. C# 11 - 파일 범위 내에서 유효한 타입 정의 (File-local types)파일 다운로드1
13116정성태8/4/20228200.NET Framework: 2041. C# - Socket.Close 시 Socket.Receive 메서드에서 예외가 발생하는 문제파일 다운로드1
... 16  17  18  19  [20]  21  22  23  24  25  26  27  28  29  30  ...