이 질문은 경쟁 조건이나 잠금 필요성과 관련 없는 C# 스레딩 동작의 잠재적인 이상 현상을 탐구합니다. 특히 우려되는 점은 스레드가 값을 캐시하고 다른 스레드의 해당 값에 대한 변경 사항을 무시하여 잠재적으로 예기치 않은 동작이 발생할 수 있는지 여부입니다.
메모리를 관리하는 NET 런타임이 이 문제를 완화할 수 있다고 믿어집니다. 그러나 일부 문헌에서는 다음과 같은 특정 코드 구조가 무한 루프로 이어질 수 있다고 주장하며 다음과 같이 주장합니다.
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 } } }
참조된 기사에 따르면(http://www.yoda.arachsys.com/) csharp/threads/volatility.shtml, http://softwareengineering.stackexchange.com/questions/104757/is-a-string-property-itself-threadsafe), 읽기 스레드는 중지 변수의 초기 값을 캐시하여 모든 후속 업데이트를 보이지 않게 렌더링하고 스레드가 무한정 실행됩니다.
그러나 메모리 모델링 전문가들은 C# 사양에서는 이러한 동작을 보장하지 않는다고 주장합니다. 제공된 코드는 일반적으로 올바르게 작동할 수 있지만 구체적인 언어 의미보다는 플랫폼 및 컴파일러별 최적화에 의존합니다.
문제를 더 자세히 설명하려면 다음 수정된 코드를 고려하세요.
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); } }
이 수정을 통해 코드는 예상대로 "Main Exit"을 출력하지만 DoWork 메서드는 무기한으로 계속 실행됩니다. 이 반례는 초기 의심에도 불구하고 C# 런타임이 스레드 전체에 걸쳐 값 업데이트의 일관성을 항상 보장하지는 않는다는 것을 보여줍니다.
이 모호성을 해결하기 위해 휘발성 키워드를 중지 변수에 적용할 수 있습니다. 휘발성 수정자는 변수에 대한 원자적 액세스를 적용하여 캐시된 값이 실제 업데이트를 가리는 것을 방지합니다.
위 내용은 C# 스레드가 다른 스레드의 값 변경을 무시할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!