스레드에 캐시된 값이 다른 스레드의 변경 사항을 무시할 수 있습니까?
이 질문은 C# 스레드가 값을 캐시하고 무시할 수 있는지 여부에 중점을 둡니다. 이후에 다른 스레드에서 해당 값이 변경되었습니다. 경쟁 조건, 원자성 및 잠금 사용에 대한 일반적인 지식에도 불구하고 조사에서는 특히 .NET 런타임이 휘발성 메모리 문제를 잠재적으로 추상화할 수 있는 시나리오를 대상으로 합니다.
일부 소스에서는 다음 코드에서 판독값이 스레드는 bool 변수 "stopping"의 초기 값을 캐시하고 수정 사항을 감지하지 못하여 잠재적으로 무한 루프로 이어질 수 있습니다.
class BackgroundTaskDemo { private bool stopping = false; static void Main() { BackgroundTaskDemo demo = new BackgroundTaskDemo(); new Thread(demo.DoWork).Start(); Thread.Sleep(5000); demo.stopping = true; } static void DoWork() { while (!stopping) { // Do something here } } }
그러나 이 주장의 타당성은 다음과 같습니다. 이의를 제기했습니다. 비평가들은 .NET 런타임이 메모리 값의 변경 사항을 실제로 무시하는지 여부에 대해 의문을 제기합니다. 그들은 주어진 코드가 "거의 확실히" 작동한다는 점을 지적하며 이는 주장이 근거가 없음을 암시합니다.
문제의 핵심은 주장에 설명된 동작이 .NET 사양에 의해 보장되지 않는다는 것입니다. 대부분의 경우 작동할 수 있지만 모든 상황에서 작동한다고 보장할 수는 없습니다. 메모리 모델 분야의 전문가들은 이러한 신뢰할 수 없는 결과에 의존하지 말라고 경고합니다.
또한 검증 가능한 반례가 제시되어 코드가 예상대로 실패하는 특정 시나리오를 보여줍니다. 다음 수정된 코드에서는 문제를 해결하기 위해 "stopping"을 휘발성으로 선언했습니다.
using System.Threading; using System; static class BackgroundTaskDemo { // make this volatile to fix it private static bool stopping = false; static void Main() { new Thread(DoWork).Start(); Thread.Sleep(5000); stopping = true; Console.WriteLine("Main exit"); Console.ReadLine(); } static void DoWork() { int i = 0; while (!stopping) { i++; } Console.WriteLine("DoWork exit " + i); } }
휘발성 키워드 없이 "release" 모드에서 실행하면 코드가 무한 루프에 들어가 무한정 계속 실행됩니다. "중지"가 true로 설정된 후에도 마찬가지입니다. 그러나 "stopping" 변수에 "휘발성"을 추가하면 문제가 해결되어 루프가 의도한 대로 종료될 수 있습니다.
결론은 코드가 작동하는 것처럼 보일 수 있지만 작동한다고 보장할 수 없다는 것입니다. 꾸준히. 강력하고 안정적인 멀티스레드 코드를 위해서는 잠금 또는 휘발성 키워드를 사용하는 것이 좋습니다.
위 내용은 C# 스레드가 부울 값을 캐시하고 다른 스레드의 후속 변경 사항을 무시할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!