gpt4 book ai didi

vb.net - 如何在 VB.net 中指定 volatile 的等效项?

转载 作者:行者123 更新时间:2023-12-04 09:22:21 28 4
gpt4 key购买 nike

我正在尝试编写用于消息传递的调用队列的无锁版本。这不是为了任何严肃的事情,只是为了学习线程。

我相对确定我的代码是正确的,除非指令被重新排序或在寄存器中完成。我知道我可以使用内存屏障来停止重新排序,但如何确保值立即写入内存?

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

最佳答案

没有等同于 C# 的 volatile VB.NET 中的关键字。相反,通常推荐的是使用 MemoryBarrier .辅助方法也可以写成:

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

还有一个有用的博客 post关于这个问题。

关于vb.net - 如何在 VB.net 中指定 volatile 的等效项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/929146/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com