Microsoft MVP성태의 닷넷 이야기
volatile 키워드 관련 질문입니다. [링크 복사], [링크+제목 복사]
조회: 10691
글쓴 사람
이성환 (vactorman at naver.com)
홈페이지
첨부 파일

스레드 사용 중에 volatile 키워드가 어떻게 동작하는 지 알아보려고 몇 가지 예제를 만들었습니다.

첨부한 예제 중에 다른 예제들은 예상한대로 동작을 하고 있는데요.

ValueUpdateTest 예제에서 이해할 수 없는 결과가 나와서 질문드립니다.

첨부한 내용을 보시면 바로 아시겠지만

Release로 빌드된 예제를 Ctrl + F5나 실행 파일로 실행해보면

메인 메서드 내부에

p._seed = 0;

이 코드가 동작하지 않는 것처럼 보입니다.

몇 번을 돌려봐도 마찬가지이고

Sleep을 짧게 줘서 t1의 동작이 실행 중인 상황에서는

p._seed 에 다른 값을 할당해도 들어가지 않네요.

그런데 이상한 건 CMD 창을 껐다 다시 켰을 때 최초 실행에서는 정상적으로

p._seed = 0 이 값이 할당 되는 것으로 표시됩니다. 그래서 JITter의 영향을 의심했는데

그 이후에는 매우 간헐적으로 p._seed = 0 이 할당되는 것으로 확인되어서

JITter 의 영향이라고 확신할 수가 없네요.
(JITter 문제라 해도 정확히 뭐가 문제인지는 모르겠습니다.)

대다수의 경우에는 t1의 for 루프 내부의 연산된 값이 표시되는 것으로 보입니다.

IL을 확인해봐도 분명히 p._seed에 0을 할당하는 구문이 생성되어 있는데요.

혹시나 해서 디버그 빌드 후 BP를 걸어서 확인해봤는데

디버그에서도 p._seed = 0; 할당문 직후에 값을 확인해 보면

0이 들어가지 않은 것으로 표시됩니다. (for 루프의 연산 중인 값이 표시됩니다)


점점 머릿속이 복잡해지는데요.

다른 예제에서 스레드가 Program 인스턴스의 필드를 사용하는 경우

참조로 전달된 인스턴스가 값복사 한 것처럼 동작하는 것은 또 어떻게 이해해야하는지


ValueUpdateTest 예제에서 스레드 별 메모리 영역이 동기화 되지 않는 다고 하더라도

메인 스레드가 직접 할당하는 값이 무시되는 것처럼 보이는게 이해가 잘 안 됩니다.


스레드 동작 방식과 스레드에 전달한 파라미터의 관계 자체가 다시 이해가 안 되기 시작합니다.


이쯤되면 스레드 사용하기가 점점 무서워지는데요.

volatile 키워드 없이 동기화를 하는 것이 정상 동작하는 지도 의심이 됩니다.


테스트 환경은 Win7 64bit i7 920에 6G 메모리 입니다.


도움 부탁 드립니다.










[최초 등록일: ]
[최종 수정일: 4/12/2013]


비밀번호

댓글 작성자
 



2013-04-15 01시10분
엄밀히 이건 volatile 의 문제는 아니고 동기화의 문제입니다. PrintType1 스레드에서 p._seed ++ 는 3가지 동작으로 이뤄집니다.

1. p._seed 의 값을 읽고,
2. p._seed 의 값을 증가하고,
3. p._seed 의 값을 쓴다.

따라서, Main 을 실행하는 스레드에서 값을 대입하는 p._seed = 0 가 제대로 동작하려면 반드시 3번 단계를 지나 1번 단계를 실행하기 전에 처리되어야 합니다. 이 현상은 매우 확률적으로 나타날 수 있기 때문에 '간헐적으로 할당'되는 것처럼 보이는 것이 맞습니다. 이를 확인하기 위해 해당 예제를 약간 변경해 다음의 경로에 올려두었으니 다운로드 받아서 실행해 보세요.

modified_VolatileTest
; https://skydrive.live.com/redir?resid=961704F5F30E2977!475

확률적이므로 경우에 따라서 한참 걸릴 수도 있지만, 결국에 한번은 0으로 초기화하는 코드가 동작하는 것을 확인할 수 있습니다.

만약, 원래 의도했던 데로 정확하게 실행하도록 프로그램을 바꾸고 싶다면 다음과 같이 코드를 수정해 주면 됩니다.

p._seed = 0; ==> Interlocked.Exchange(ref p._seed, 0);

p._seed ++; ==> Interlocked.Increment(ref p._seed);
정성태
2013-04-16 12시14분
[이성환] 답변 감사드립니다.

이 예제를 만들어 테스트 한 이유는 volatile의 설명 중에

"항상 최신값을 유지할 수 있다"는 표현 때문이었습니다.

제가 이 표현을 곡해했다고 봐야할 듯 하네요.

저는 이 표현을 volatile 키워드를 사용한 필드 접근 시 내부적으로 lock을 구현해
값의 할당을 항상 보장할 수 있다는 정도의 의미로 해석했습니다.

결국 항상 정확한 값을 얻으려면 Interlock을 쓰든 크리티컬 섹션을 걸든
동기화를 해야만 한다는 것이 결론이었군요.

음... 그러면 이제 volatile을 사용하는 의미가 점점 더 모호해집니다.

이런 동기화 문제가 있다면 처음부터 volatile 사용을 배제하고
배타제어를 하는 것이 더 옳은 방향 같은데

필드 접근에 대해서 volatile만으로 동기화 문제를 완전히 해결할 수 없다면
volatile을 굳이 써야할 이유가 있을까요?
전 그냥 필드를 프로퍼티로 바꿔서 lock을 걸어주는 게 더 안정적일 것 같은데......
(물론 코드가 더 길어지고 동기화 객체도 추가로 필요하겠지만)

volatile의 사용 의미가 더 궁금해 집니다.

기초가 없어서 그런지 부끄럽게도 초보적인 질문만 계속하게 되네요.
[guest]
2013-04-16 01시23분
volatile 은 시스템의 캐시에 보관된 변수를 무효화시켜서 다시 읽어오게 하는 의미와, 컴파일러의 최적화를 방지하는 것에 그 목적이 있습니다. C# 예제는 아니지만, C++ 로 된 다음의 글을 참고해 보세요.

volatile 키워드
; http://www.sysnet.pe.kr/2/0/413
정성태

... 31  32  33  34  35  36  [37]  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
4935몬난아12/28/201711479IIS 및 ASP.NET 이 서버에서의 동작방식? [2]
4934Ques...12/26/201721798C# 해상도에 따른 자동 사이즈 조절방법이 궁금합니다. [3]
4933Kay12/15/20179153C# VS 버전 에러 질문 드립니다. [1]파일 다운로드1
4932정환나라12/13/20179072vs2013에서 빌드한 com 컨트롤 객체를 닷넷 2.0에서 사용하려 합니다 [4]
4931Arvid12/12/201710098Visual Studio 2012 c# using문 참조 에러 [5]파일 다운로드1
4929김성대12/8/20178600app.config에 관한질문입니다. [1]
4928김성대12/7/20179258SQL Server 설치에러에 대한 질문입니다. [1]파일 다운로드1
4926heyh...12/6/20178491[삭제] ContextSwitchDeadlock????
4925ho12/5/20179029[삭제] WebBrowser로 드롭박스 로그인 페이지 탐색 시 발생한 문제에 대해 질문 올립니다.파일 다운로드2
4924몽중언12/3/20179474C# 디버깅 모드에서만 DB Insert가 되는 현상 질의 [6]
4923고요한11/23/20179599파일 확장자에 연결된 프로그램을 등록하는 방법에 대한 질문입니다. [2]
4922박성훈11/23/201710559시작하세요! C# 7.1 학습 방법 [3]
4921초보개발자11/20/20177792[삭제] 폼 사이즈 질문드립니다.
4920Ques...11/19/20178913IEnumerable 의 "지연된 평가" 에 관하여 질문드립니다. [2]파일 다운로드1
4919mskim11/16/20179187Split()을 이용하여 문자 구분 시 구분문자도 같이 저장하는 방법이 있나요? [2]
4917ho11/16/20179833WPF XAML 트리거 관련해 문의 드립니다. [3]
4918ho11/16/201710125    답변글 [답변]: 예제 프로젝트 첨부합니다. [4]파일 다운로드2
4916필승11/11/20179785기본 웹 브라우저 체크는 어떻게 해야 하나요? [2]
4915필승11/10/20178858WebBrowser 컨트롤 소리 출력 문의 드립니다. [2]
4914Ques...11/10/20179543c# 버튼 이벤트에 관하여 질문드립니다. [2]
4913Arvid11/8/201711957Log4Net 라이브러리를 이용하여 특정 기간이 지났을 때 자동 로그 삭제 기능 구현 질문 드립니다! [2]
4912조범희11/8/201711630C# FTP 다운로드중 에러 발생.. [2]파일 다운로드1
4911필승11/6/201710068WebBrowser 컨트롤 사용법에 대해 궁금합니다. [2]
4910진우11/6/20179651람다 초보 질문 드립니다. [2]
4909필승11/5/201710581TextBox에 관해 질문 드립니다. [5]
4908필승11/1/201713911특정 시각에 프로그램 종료 또는 재시작시 오류 발생 [8]
... 31  32  33  34  35  36  [37]  38  39  40  41  42  43  44  45  ...