문제

메시지 전달에 사용하는 호출 대기열의 잠금 장치 버전을 작성하려고합니다. 이것은 스레딩에 대해 배우는 것만으로도 심각한 것이 아닙니다.

지침이 레지스터에서 다시 주문되거나 완료된 경우를 제외하고 내 코드가 정확하다고 확신합니다. 메모리 장벽을 사용하여 재정렬을 중지 할 수 있다는 것을 알고 있지만, 값이 즉시 메모리에 기록되도록하려면 어떻게해야합니까?

Public Class CallQueue
    Private first As New Node(Nothing) 'owned by consumer'
    Private last As Node = first 'owned by producers'
    Private Class Node
        Public ReadOnly action As Action
        Public [next] As Node
        Public Sub New(ByVal action As Action)
            Me.action = action
        End Sub
    End Class

    Private _running As Integer
    Private Function TryAcquireConsumer() As Boolean
        Threading.Thread.MemoryBarrier()

        'Dont bother acquiring if there are no items to consume'
        'This unsafe check is alright because enqueuers call this method, so we never end up with a non-empty idle queue'
        If first.next Is Nothing Then Return False

        Threading.Thread.MemoryBarrier()

        'Try to acquire'
        Return Threading.Interlocked.Exchange(_running, 1) = 0
    End Function
    Private Function TryReleaseConsumer() As Boolean
        Do
            Threading.Thread.MemoryBarrier()

            'Dont release while there are still things to consume'
            If first.next IsNot Nothing Then Return False

            Threading.Thread.MemoryBarrier()

            'Release'
            _running = 0

            Threading.Thread.MemoryBarrier()

            'It is possible that a new item was queued between the first.next check and releasing'
            'Therefore it is necessary to check if we can re-acquire in order to guarantee we dont leave a non-empty queue idle'
            If Not TryAcquireConsumer() Then Return True
        Loop
    End Function

    Public Sub QueueAction(ByVal action As Action)
        'Enqueue'
        'Essentially, this works because each node is returned by InterLocked.Exchange *exactly once*'
        'Each node has its .next property set exactly once, and also each node is targeted by .next exactly once, so they end up forming a valid tail'
        Dim n = New Node(action)
        Threading.Interlocked.Exchange(last, n).next = n

        'Start the consumer thread if it is not already running'
        If TryAcquireConsumer() Then
            Call New Threading.Thread(Sub() Consume()).Start()
        End If
    End Sub
    Private Sub Consume()
        'Run until queue is empty'
        Do Until TryReleaseConsumer()
            first = first.next
            Call first.action()
        Loop
    End Sub
End Class
도움이 되었습니까?

해결책

사용 Thread.VolatileRead() 그리고 VolatileWrite() BCL의 방법.

http://msdn.microsoft.com/en-us/library/system.threading.thread.volatileread.aspx

다른 팁

C#과 동등한 것은 없습니다 volatile vb.net의 키워드. 대신에 종종 권장되는 것은 사용입니다 메모리 배리어. 도우미 방법도 작성할 수 있습니다.

Function VolatileRead(Of T)(ByRef Address As T) As T
    VolatileRead = Address
    Threading.Thread.MemoryBarrier()
End Function

Sub VolatileWrite(Of T)(ByRef Address As T, ByVal Value As T)
    Threading.Thread.MemoryBarrier()
    Address = Value
End Sub

또한 유용한 블로그가 있습니다 게시하다 이 주제에 대해.

.NET 4.5에서 시작하여 BCL에 두 가지 새로운 방법을 추가하여 volatile 예어: 휘발성. 읽기 그리고 volatile.write. 그들은 읽기/쓰기와 완전히 동일해야합니다. volatile 필드. vb.net에서 명확하게 사용할 수 있습니다. 그들은 더 나은 (어디 더 나은 == 더 빠르게)보다 Thread.VolatileRead/Thread.VolatileWrite 전체 울타리 대신 반 울타리를 사용하기 때문입니다.

나는이 주제에 대한 전문가가 아니므로 내가 틀렸다면 다른 사람이 나를 바로 잡을 수 있기를 바랍니다. 내가 이해 한 바에 따르면, 메모리 최적화 문제는 현재 이론적 인 문제이며 반드시 실제로 일어날 일은 아닙니다. 그러나 메모리 배거에 관계없이 메모리 액세스에 연동 API를 사용하면 영향을받지 않을 것이라고 생각합니다.

불행히도 VB.NET에는 휘발성과 동등한 것이 없습니다. 일반적인 속성으로 장식되지는 않지만 오히려 특수 컴파일러 생성 수정 자입니다. 이런 종류의 필드가있는 유형을 방출하려면 반사를 사용해야합니다.

다음은 .NET Framework에서 스레딩에 대한 질문이있을 때 자주 참조하는 리소스입니다. 매우 길지만 유용하게 찾을 수 있기를 바랍니다.

http://www.yoda.arachsys.com/csharp/threads/printable.shtml

mono.cecil reader 코드는 fieldType를 system.runtime.compilerservices.isvolatile으로 modifiertype를 사용하여 QuessedModifierType로 만듭니다.

또한 thread.volatileRead () 및 thread.volatilewrite ()를 사용하여 "휘발성"에 대한 속성을 작성하고 다음과 같은 속성으로 모든 속성/변수를 만들 수 있습니다.

<Volatile()>
Protected Property SecondsRemaining as Integer

이것을 어딘가에 썼지 만 지금은 찾을 수없는 것 같습니다 ...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top