Interlocked.在32位系统上添加不带线程安全线程 [英] Interlocked.Add Not Thread Safe with Longs on a 32bit system
问题描述
以下是控制台应用程序的三个类。如果分成三个单独的文件,子main()将启动多个线程添加和
删除相同的值。最后,我们期望所有
余额的值为0.使用整数时,一切正常。 LONGS做
没有。
我们正在使用Interlocked方法。我相信在32位系统上使用long时,Interlocked.Add
方法不是线程安全的。
我们知道Interlocked.Read(dotnet 2.0的新功能) )对于32位系统上的多头需要
,但是dotnet框架错过了一个技巧
这里微软推出了一种新的阅读方法但是没有
使.Add方法正常工作。
注意:这可以在单核单个procssors上找到。
但是没有在多核或双核或超线程奔腾4上。
选项明确开启
选项严格上
< br $>
模块模块1
公共柜员(99)作为柜员
私人主题(99)As Threading.Thread
Sub Main()
我的整数= 0到99
Tellers(我)=新出纳员
下一页
请
我的整数= 0到99
昏暗t As New Threading.Thread(AddressOf
Tellers(i).DoWork)
主题(i)= t
t.Start()
下一页
我的整数= 0到99
主题(i).Join()
下一页
Dim B2 As Integer = BankInt.Balance
Console.WriteLine(" Int Balance" &安培; B2)
Dim B1 As Long = BankLong.Balance
Console.WriteLine(Long Balance"& B1)
循环
结束子
结束模块
>
明确选项
选项严格上限
进口System.Threading
>
公共班级柜员
Public Sub DoWork()
我的整数= 1到100000
< br $>
BankInt.Deposit(50)
BankInt.Withdraw(50)
BankLong.Deposit(50)
BankLong.Withdraw(50)
下一页
End Sub
结束班级
选项明确开启
选项严格开启
进口系统。线程
公共类BankLong
私人共享_balance持续
公共共享ReadOnly Property Balance()As Long
获取
返回Interlocked.Read(_balance)
结束获取
结束物业
公共共享子存款(ByVal金额一样长)
Interlocked.Add(_balance,Amount)
结束子
公共共享子提款(ByVal金额一样长)
Interlocked.Add(_balance,-Amount)
结束子
结束班
公共类BankInt
私有共享_balance作为整数
公共共享ReadOnly财产余额()为整数
获取
返回_balance
结束获取
结束物业
公共共享子存款(ByVal金额为整数)
Interlocked.Add(_balance,Amount)
End Sub
公共共享子提款(ByVal Amount As整数)
Interlocked.Add(_balance,-Amount)
End Sub
结束班
大卫,
Interlocked.Add是线程-safe for Int64。那么问题出在哪里?请仔细看看
的Withdrawl方法。你正在做一个无锁的
对Int64的否定。
Brian
David写道:
以下是控制台应用程序的三个类。如果分成三个单独的文件,子main()将启动多个线程添加和
删除相同的值。最后,我们期望所有
余额的值为0.使用整数时,一切正常。 LONGS做
没有。
我们正在使用Interlocked方法。我相信在32位系统上使用long时,Interlocked.Add
方法不是线程安全的。
我们知道Interlocked.Read(dotnet 2.0的新功能) )对于32位系统上的多头需要
,但是dotnet框架错过了一个技巧
这里微软推出了一种新的阅读方法但是没有
使.Add方法正常工作。
注意:这可以在单核单个procssors上找到。
但是没有在多核或双核或超线程奔腾4上。
选项明确开启
选项严格上
模块模块1
公共柜员(99)作为柜员
私人话题(99)As Threading.Thread
Sub Main()
我的整数= 0到99
Tellers(i)=新柜员
下一页
做
对于i as Integer = 0到99
Dim t As New Threading.Thread(AddressOf
Tellers(i).DoWork )
主题(i)= t
t.Start()
下一步
我的整数= 0到99
线程(i).Join()
下一页
Dim B2 As Integer = BankInt.Balance
Console.WriteLine(" Int Balance" &安培; B2)
Dim B1 As Long = BankLong.Balance
Console.WriteLine(Long Balance"& B1)
循环
结束次级
结束模块
>
明确选项
选项严格开启
进口System.Threading >
公共班级柜员
公共子工作()
我的整数= 1到100000
BankInt.Deposit(50)
BankInt.Withdraw(50)
BankLong.Deposit (50)
BankLong.Withdraw(50)
下一页
End Sub
结束课
选项明确开启
期权严格开启
进口系统。线程
公共类BankLong
私人共享_bal很长时间
公共资源ReadOnly财产余额()长期
获取
返回Interlocked.Read(_balance)
结束获取
结束物业
公共共享次级存款(ByVal金额一样长)
Interlocked.Add(_balance,金额)
结束子
Public Shared Sub Withdraw(ByVal Amount as Long)
Interlocked.Add(_balance,-Amount)
End Sub >
结束班级
公共类别BankInt
私人共享_balance作为整数
>
公共共享ReadOnly财产余额()为整数
获取
返回_balance
结束获取
结束物业
公共共享次级存款(ByVal金额为整数)
Interlocked.Add(_balance,Amount)
End Sub
公共共享子提款(ByVal金额为整数)
/>
Interlocked.Add(_balance,-Amount)
结束子
结束等级
Brian Gideon写道:
David,
Interlocked.Add对Int64是线程安全的。那么问题出在哪里?请仔细看看
的Withdrawl方法。你正在做一个无锁的
否定Int64。
Brian
$ b $嗯......我相信我说得太早了。我刚注意到
Withdraw方法中的金额在堆栈中。当我有时间时,我将不得不用一点点来看看这个。
David,
我只是没有看到代码有问题。好吧,除了你
真的需要一个电话Interlocked.Read在BankInt.Balance属性,
但这不会导致你看到的问题。我会尝试
记得在我的双核笔记本电脑上运行这个代码(不是我在
时刻),它上面有VS 2005。 />
最后看到多少余额?
Brian
David写道:
以下是控制台应用程序的三个类。如果分成三个单独的文件,子main()将启动多个线程添加和
删除相同的值。最后,我们期望所有
余额的值为0.使用整数时,一切正常。 LONGS做
没有。
我们正在使用Interlocked方法。我相信在32位系统上使用long时,Interlocked.Add
方法不是线程安全的。
我们知道Interlocked.Read(dotnet 2.0的新功能) )对于32位系统上的多头需要
,但是dotnet框架错过了一个技巧
这里微软推出了一种新的阅读方法但是没有
使.Add方法正常工作。
注意:这可以在单核单个procssors上找到。
但是没有在多核或双核或超线程奔腾4上。
选项明确开启
选项严格上
模块模块1
公共柜员(99)作为柜员
私人话题(99)As Threading.Thread
Sub Main()
我的整数= 0到99
Tellers(i)=新柜员
下一页
做
对于i as Integer = 0到99
Dim t As New Threading.Thread(AddressOf
Tellers(i).DoWork )
主题(i)= t
t.Start()
下一步
我的整数= 0到99
线程(i).Join()
下一页
Dim B2 As Integer = BankInt.Balance
Console.WriteLine(" Int Balance" &安培; B2)
Dim B1 As Long = BankLong.Balance
Console.WriteLine(Long Balance"& B1)
循环
结束次级
结束模块
>
明确选项
选项严格开启
进口System.Threading >
公共班级柜员
公共子工作()
我的整数= 1到100000
BankInt.Deposit(50)
BankInt.Withdraw(50)
BankLong.Deposit (50)
BankLong.Withdraw(50)
下一页
End Sub
结束课
选项明确开启
期权严格开启
进口系统。线程
公共类BankLong
私人共享_bal很长时间
公共资源ReadOnly财产余额()长期
获取
返回Interlocked.Read(_balance)
结束获取
结束物业
公共共享次级存款(ByVal金额一样长)
Interlocked.Add(_balance,金额)
结束子
Public Shared Sub Withdraw(ByVal Amount as Long)
Interlocked.Add(_balance,-Amount)
End Sub >
结束班级
公共类别BankInt
私人共享_balance作为整数
>
公共共享ReadOnly财产余额()为整数
获取
返回_balance
结束获取
结束物业
公共共享次级存款(ByVal金额为整数)
Interlocked.Add(_balance,Amount)
End Sub
公共共享子提款(ByVal金额为整数)
/>
Interlocked.Add(_balance,-Amount)
结束子
结束等级
Below are three classes for a console application. If put into three
separate files, the sub main() will launch multiple threads adding and
removing the same value. At the end we expect the value for all
Balances to be 0. When using an Integer things work fine. LONGS do
not.
We are using the Interlocked methods. I believe the Interlocked.Add
method is not thread safe when using longs on 32bit systems.
We are aware of Interlocked.Read (new to dotnet 2.0) which is required
for longs on 32bit systems, but is the dotnet framework missing a trick
here as Microsoft have introduced a new method for reading but haven''t
got the .Add method to work correctly.
Note: This works find on single core single procssors.
But does not on muli-core or dual-core or hyper-threaded pentium 4.
Option Explicit On
Option Strict On
Module Module1
Public Tellers(99) As Teller
Private Threads(99) As Threading.Thread
Sub Main()
For i As Integer = 0 To 99
Tellers(i) = New Teller
Next
Do
For i As Integer = 0 To 99
Dim t As New Threading.Thread(AddressOf
Tellers(i).DoWork)
Threads(i) = t
t.Start()
Next
For i As Integer = 0 To 99
Threads(i).Join()
Next
Dim B2 As Integer = BankInt.Balance
Console.WriteLine("Int Balance " & B2)
Dim B1 As Long = BankLong.Balance
Console.WriteLine("Long Balance " & B1)
Loop
End Sub
End Module
Option Explicit On
Option Strict On
Imports System.Threading
Public Class Teller
Public Sub DoWork()
For i As Integer = 1 To 100000
BankInt.Deposit(50)
BankInt.Withdraw(50)
BankLong.Deposit(50)
BankLong.Withdraw(50)
Next
End Sub
End Class
Option Explicit On
Option Strict On
Imports System.Threading
Public Class BankLong
Private Shared _balance As Long
Public Shared ReadOnly Property Balance() As Long
Get
Return Interlocked.Read(_balance)
End Get
End Property
Public Shared Sub Deposit(ByVal Amount As Long)
Interlocked.Add(_balance, Amount)
End Sub
Public Shared Sub Withdraw(ByVal Amount As Long)
Interlocked.Add(_balance, -Amount)
End Sub
End Class
Public Class BankInt
Private Shared _balance As Integer
Public Shared ReadOnly Property Balance() As Integer
Get
Return _balance
End Get
End Property
Public Shared Sub Deposit(ByVal Amount As Integer)
Interlocked.Add(_balance, Amount)
End Sub
Public Shared Sub Withdraw(ByVal Amount As Integer)
Interlocked.Add(_balance, -Amount)
End Sub
End Class
David,
Interlocked.Add is thread-safe for Int64. So where''s the problem? Take
a closer look at the Withdrawl method. You''re doing a lock-free
negation of an Int64.
Brian
David wrote:Below are three classes for a console application. If put into three
separate files, the sub main() will launch multiple threads adding and
removing the same value. At the end we expect the value for all
Balances to be 0. When using an Integer things work fine. LONGS do
not.
We are using the Interlocked methods. I believe the Interlocked.Add
method is not thread safe when using longs on 32bit systems.
We are aware of Interlocked.Read (new to dotnet 2.0) which is required
for longs on 32bit systems, but is the dotnet framework missing a trick
here as Microsoft have introduced a new method for reading but haven''t
got the .Add method to work correctly.
Note: This works find on single core single procssors.
But does not on muli-core or dual-core or hyper-threaded pentium 4.
Option Explicit On
Option Strict On
Module Module1
Public Tellers(99) As Teller
Private Threads(99) As Threading.Thread
Sub Main()
For i As Integer = 0 To 99
Tellers(i) = New Teller
Next
Do
For i As Integer = 0 To 99
Dim t As New Threading.Thread(AddressOf
Tellers(i).DoWork)
Threads(i) = t
t.Start()
Next
For i As Integer = 0 To 99
Threads(i).Join()
Next
Dim B2 As Integer = BankInt.Balance
Console.WriteLine("Int Balance " & B2)
Dim B1 As Long = BankLong.Balance
Console.WriteLine("Long Balance " & B1)
Loop
End Sub
End Module
Option Explicit On
Option Strict On
Imports System.Threading
Public Class Teller
Public Sub DoWork()
For i As Integer = 1 To 100000
BankInt.Deposit(50)
BankInt.Withdraw(50)
BankLong.Deposit(50)
BankLong.Withdraw(50)
Next
End Sub
End Class
Option Explicit On
Option Strict On
Imports System.Threading
Public Class BankLong
Private Shared _balance As Long
Public Shared ReadOnly Property Balance() As Long
Get
Return Interlocked.Read(_balance)
End Get
End Property
Public Shared Sub Deposit(ByVal Amount As Long)
Interlocked.Add(_balance, Amount)
End Sub
Public Shared Sub Withdraw(ByVal Amount As Long)
Interlocked.Add(_balance, -Amount)
End Sub
End Class
Public Class BankInt
Private Shared _balance As Integer
Public Shared ReadOnly Property Balance() As Integer
Get
Return _balance
End Get
End Property
Public Shared Sub Deposit(ByVal Amount As Integer)
Interlocked.Add(_balance, Amount)
End Sub
Public Shared Sub Withdraw(ByVal Amount As Integer)
Interlocked.Add(_balance, -Amount)
End Sub
End Class
Brian Gideon wrote:David,
Interlocked.Add is thread-safe for Int64. So where''s the problem? Take
a closer look at the Withdrawl method. You''re doing a lock-free
negation of an Int64.
BrianHmm...I believe I spoke too soon. I just noticed that Amount in the
Withdraw method is on the stack. I''ll have to look at this in a little
more detail when I get time.
David,
I''m just not seeing a problem with the code. Well, except that you
really need a call Interlocked.Read in the BankInt.Balance property,
but that wouldn''t cause the problem you''re seeing. I''ll try to
remember to run this code on my dual-core laptop (not with me at the
moment) which has VS 2005 on it.
What balance are seeing at the end with longs?
Brian
David wrote:Below are three classes for a console application. If put into three
separate files, the sub main() will launch multiple threads adding and
removing the same value. At the end we expect the value for all
Balances to be 0. When using an Integer things work fine. LONGS do
not.
We are using the Interlocked methods. I believe the Interlocked.Add
method is not thread safe when using longs on 32bit systems.
We are aware of Interlocked.Read (new to dotnet 2.0) which is required
for longs on 32bit systems, but is the dotnet framework missing a trick
here as Microsoft have introduced a new method for reading but haven''t
got the .Add method to work correctly.
Note: This works find on single core single procssors.
But does not on muli-core or dual-core or hyper-threaded pentium 4.
Option Explicit On
Option Strict On
Module Module1
Public Tellers(99) As Teller
Private Threads(99) As Threading.Thread
Sub Main()
For i As Integer = 0 To 99
Tellers(i) = New Teller
Next
Do
For i As Integer = 0 To 99
Dim t As New Threading.Thread(AddressOf
Tellers(i).DoWork)
Threads(i) = t
t.Start()
Next
For i As Integer = 0 To 99
Threads(i).Join()
Next
Dim B2 As Integer = BankInt.Balance
Console.WriteLine("Int Balance " & B2)
Dim B1 As Long = BankLong.Balance
Console.WriteLine("Long Balance " & B1)
Loop
End Sub
End Module
Option Explicit On
Option Strict On
Imports System.Threading
Public Class Teller
Public Sub DoWork()
For i As Integer = 1 To 100000
BankInt.Deposit(50)
BankInt.Withdraw(50)
BankLong.Deposit(50)
BankLong.Withdraw(50)
Next
End Sub
End Class
Option Explicit On
Option Strict On
Imports System.Threading
Public Class BankLong
Private Shared _balance As Long
Public Shared ReadOnly Property Balance() As Long
Get
Return Interlocked.Read(_balance)
End Get
End Property
Public Shared Sub Deposit(ByVal Amount As Long)
Interlocked.Add(_balance, Amount)
End Sub
Public Shared Sub Withdraw(ByVal Amount As Long)
Interlocked.Add(_balance, -Amount)
End Sub
End Class
Public Class BankInt
Private Shared _balance As Integer
Public Shared ReadOnly Property Balance() As Integer
Get
Return _balance
End Get
End Property
Public Shared Sub Deposit(ByVal Amount As Integer)
Interlocked.Add(_balance, Amount)
End Sub
Public Shared Sub Withdraw(ByVal Amount As Integer)
Interlocked.Add(_balance, -Amount)
End Sub
End Class
这篇关于Interlocked.在32位系统上添加不带线程安全线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!