提问人:CodeAdze 提问时间:4/23/2023 最后编辑:CodeAdze 更新时间:4/24/2023 访问量:58
VB.Net 中多线程方法中局部变量的行为
Behaviour Of Local Variables In A Multi-Threaded Method In VB.Net
问:
下面的代码摘自 MSDN 中的示例。这是关于如何使用的示例,但在我看来,其中有一个竞争条件。
为什么我认为这是因为方法中的线条。在我看来,可能会发生以下情况:SpinLock
Dim lockTaken As Boolean = False
UpdateWithSpinLock
线程 1 进入方法并执行,并发生上下文切换。
线程 1 现在具有 和 为 True。
线程 2 进入并仅执行到行 。
线程 2 现在已设置回 False,并发生上下文切换。
线程 1 继续并在块中进行测试,发现它是 False(线程 1 应该是 True),因此不会释放 .
线程 1 退出该方法,使锁留在原位,线程 2 永远等待。UpdateWithSpinLock
_queue.Enqueue(d)
SpinLock
lockTaken
Dim lockTaken As Boolean = False
lockTaken
lockTaken
Finally
SpinLock
Imports System.Threading
Imports System.Threading.Tasks
Class SpinLockDemo2
Const N As Integer = 100000
Shared _queue = New Queue(Of Data)()
Shared _lock = New Object()
Shared _spinlock = New SpinLock()
Class Data
Public Name As String
Public Number As Double
End Class
Shared Sub Main()
UseSpinLock()
Console.WriteLine("Press a key")
Console.ReadKey()
End Sub
Private Shared Sub UpdateWithSpinLock(ByVal d As Data, ByVal i As Integer)
Dim lockTaken As Boolean = False
Try
_spinlock.Enter(lockTaken)
_queue.Enqueue(d)
Finally
If lockTaken Then
_spinlock.Exit(False)
End If
End Try
End Sub
Private Shared Sub UseSpinLock()
Dim sw = Stopwatch.StartNew()
Parallel.Invoke(
Sub()
For i As Integer = 0 To N - 1
UpdateWithSpinLock(New Data() With {.Name = i.ToString(), .Number = i}, i)
Next
End Sub,
Sub()
For i As Integer = 0 To N - 1
UpdateWithSpinLock(New Data() With {.Name = i.ToString(), .Number = i}, i)
Next
End Sub
)
sw.Stop()
Console.WriteLine("elapsed ms with spinlock: {0}", sw.ElapsedMilliseconds)
End Sub
End Class
我对此的解释是否正确。如果不是,你能告诉我我错过了什么。
答:
2赞
jmcilhinney
4/23/2023
#1
在该代码中,是一个局部变量,因此在一个线程中运行的该方法的任何实例都不能更改在另一个线程上运行的方法的另一个实例中该变量的值。您所描述的内容需要一个成员变量。lockTaken
lockTaken
评论
0赞
CodeAdze
4/23/2023
感谢您的回答,让我感到困惑的是该方法是共享的,因此不是每个线程都使用相同的方法“实例”来设置和重置相同的方法吗?UpdateWithSpinLock
lockTaken
1赞
jmcilhinney
4/23/2023
@CodeAdze,如果该方法不是,并且您在同一对象上多次调用它,您是否希望在调用之间共享局部变量?我猜不是,那么为什么一种方法的行为应该不同呢? 仅表示类型一个,而不是每个类型的实例一个。但是,每个方法调用仍然是独立的。Shared
Shared
Shared
0赞
CodeAdze
4/24/2023
。您是否希望在调用之间共享局部变量?我猜不是......不幸的是,这就是我的误解所在。正如 @Hanns Passant 所解释的那样,我不知道每个线程都有自己的堆栈和局部变量值,所以我认为如果 thread2 在 thread1 退出之前输入了一个方法,那么 thread2 将开始重新设置 thread1 仍在操作的局部变量值。我有一种感觉,我误解了某些东西,因为我的思维导致我一直在抓取 s,这基本上使我所谓的并行代码同步执行。SyncLock
1赞
Craig
4/24/2023
Shared
表示例程不在类的单个实例的上下文中运行---与普通成员例程不同,没有 .它仍然可以访问私有和受保护的成员(给定一个实例作为参数、内部构造或以其他方式获取)。它不会改变例程自身变量的行为方式。如果您要访问任何变量,或者要访问共享实例上的任何内容,您仍然可能会遇到比赛。Me
Shared
评论