2011-01-14 5 views
3

다음과 같은 코드에서 Proc1과 Proc2가 서로 다른 프로세서에서 동시에 실행되는 경우 ThingVal2가 5가 아닌 값 (예 : 0)을 가져올 수 있습니까?필드를 역 참조 할 때 메모리 장벽이 필요합니까 (.net x86 또는 x64)?

 
Class SimpleThing 
    Public X As Integer 
    Sub New(ByVal value As Integer) 
     X = value 
    End Sub 
End Class 
Class ConcurrencyTest 
    Dim Thing1 As New SimpleThing(5) 
    Dim Thing2 As New SimpleThing(0) 
    Dim ThingRef As SimpleThing = Thing1 
    Dim ThingVal1, ThingVal2 As Integer 
    Sub Proc1() 
     Thing2.X = 5 
     Threading.Thread.MemoryBarrier() 
     ThingRef = Thing2 
    End Sub 
    Sub Proc2() 
     ThingVal1 = Thing2.X 
     ThingVal2 = ThingRef.X 
    End Sub 
End Class 

나는 IA64 같은 약한 모델, PROC2이 변경된 것으로 ThingRef 볼 수 있지만 그렇게 한 것으로 Thing2의 필드 X를 볼 수있는 실제 가능성이 있다는 것을 알고있다. x86 또는 x64에서 실행되는 .Net 응용 프로그램에 대한 위험이 있습니까? Proc1이 SimpleThing의 새 인스턴스를 만든 경우 X 필드를 5로 설정 한 다음 ThingRef가이를 가리 키도록 설정하면 위험을 피하기에 충분하거나 새로운 것이 캐시 라인에 할당 될 가능성이 있습니다 Proc2 스레드가 액세스 한 다른 것과 공유 되었습니까?

멀티 스레드 코드를 사용하는 일반적인 패러다임은 불변 개체를 구성하고이를 가리 키도록 변경 가능한 참조를 설정하는 것입니다 (아마도 Interlocked.CompareExchange를 사용하여). 스레딩에 관계없이 불변 타입을 읽는 것이 x86/x64에서 항상 안전합니까? 아니면 문제를 일으킬 수 있습니까? 후자의 경우 신뢰할 수있는 동작을 보장하기 위해 vb.net에서 선호되는 방법은 무엇입니까?

또한 이러한 문제가 발생할 수없는 방식으로 코드를 실행해야한다고 지정하는 방법이 있습니까 (예 : 올바른 작동을 보장 할 수없는 IA64와 같은 단일 코어로 실행 제한).

+0

값을 한 번만 읽으면 변경 불가능합니다. Int와 bool이 해당 카테고리에 속합니다. 길지는 않지만 확실히 문자열은 아닙니다. – SRM

+0

@SRM : 불변 개체는 다른 사람이 참조를 사용할 수있게되면 변경되지 않습니다.위의 'SimpleThing'객체는 .net x86 및 .net x64 메모리 모델에서 보장되는 것과없는 것을 정확하게 묻기 때문에 변경 불가능하지 않습니다. – supercat

답변

0

많은 질문을 던졌습니다. 내가 아는 것에 대답하려고 노력할 것이다.

-1. 광고 코드 예 :

CLR 2.0부터 매장을 주문했습니다. 즉, ThingVal은 x86/x64에서 항상 5가됩니다. 확실히. 실제 IA64에서 시도하지는 않았지만 IA64에서도 잘 작동합니다. CLR이 모든 플랫폼에서 순서가 지정된 쓰기를 보장해야하고 간단한 예제만으로 충분해야하기 때문입니다.

-2. IA64 대 x86/x64 :

x86/x64는 메모리 의미가 다르며 IA64와 같은 위험 요소가 없습니다. 여기서 가능한 유일한 문제는 실제로 더 높은 수준의 언어를 사용하고 있고 C++과 같은 최적화 컴파일러를 사용하면 컴파일러가 최적화를 수행하는 방법을 정확히 모른 채 아무것도 예측할 수 없다는 것입니다. 설명되지 않음 : VB는 전역 최적화 등을 수행하지 않으므로 코드가 안전해야합니다.

-3. 광고 불변 :

당신이 정말로 그것을 읽었을 때 정말로 불변이라면, 그것은 안전합니다.

-4. 광고 싱글 코어 :

스레드 선호도를 설정할 수 있습니다. 이것은 각 스레드의 표준 속성이며 스레드가 실행할 수있는 CPU를 정의합니다. (.net의 스레드 선호도 설정은 운영 체제의 선호도를 직접 변경합니다.)하지만 프로그램이 느리게 실행됩니다.

또한 C#으로 전환하고 휘도가 인 키워드를 사용할 수 있습니다. 모든 CPU에서 즉시 나타나는 휘발성 변수를 변경하고 여기에서 제시 한 모든 가능한 문제를 해결할 것이므로 사용자가 더 쉽게 살 수 있습니다. 불행히도 VB는이 키워드를 제공하지 않습니다.

+0

저는 x86이 상점을 주문했음을 알고 있습니다 만, 여기서 문제는로드 종속성 때문입니다. Instance2.X 또는 ThingRef가 작성되기 전에 instance2의 필드 X를 Proc2에서 읽을 수있었습니다. .NET에서, 코드가 ThingRef.X를 읽을 때 단순히 Instance2.X의 읽기에서 캐시 된 값을 사용하지 않을 것이라는 보장이 있습니까? 그것은 내가 듣지 못한 코너 케이스입니다. – supercat

+0

일부 스레드는 예를 들어. 코어 # 5,하지만 그것은 지나치게 특별하게 보입니다. 실제로 필요한 것은 두 개 이상의 스레드가 서로 다른 프로세서에서 동시에 실행되어서는 안되며 한 프로세서에서 다른 프로세서로 이동할 때마다 이전 프로세서와 새 프로세서가 순서대로 캐시를 플러시해야한다는 것입니다. – supercat

+0

예, "ordered stores"는 ThingRef.X를 읽을 때 새로운 ThingRef와 새 X 또는 오래된 ThingRef와 오래된 X를 읽습니다. X가 ThingRef 안에 있기 때문에 X보다 먼저 ThingRef를 읽습니다. 그래서 안전합니다. 동일한 물체 안에 X1과 X2가 있고 서로 관련되어 있다면 주문한 상점에서도 안전하지 않을 수 있습니다. –