下面的测试代码(F#)没有返回我期望的结果:
let safeCount() =
let n = 1000000
let counter = ref 0
let spinlock = ref <| SpinLock(false)
let run i0 i1 () =
for i=i0 to i1-1 do
let locked = ref false
try
(!spinlock).Enter locked
if !locked then
counter := !counter + 1
finally
if !locked then
(!spinlock).Exit()
let thread = System.Threading.Thread(run 0 (n/2))
thread.Start()
run (n/2) n ()
thread.Join()
!counter我预计SpinLock会互相排除计数器,因此,它会返回1,000,000的计数,但实际上,它会返回较小的值,就好像没有发生互斥一样。
知道出什么事了吗?
发布于 2010-06-12 05:19:54
编辑: Stephen Swensen有一种方法可以直接访问下面的引用样式SpinLock。!返回一个结构的副本,所以在这种情况下不应该使用它。
您可以将SpinLock包装在一个类中(我尝试使用静态和不可变的SpinLock,但没有效果)。
type SpinLockClass() =
let s = System.Threading.SpinLock(false)
member x.Enter locked = s.Enter(locked)
member x.Exit() = s.Exit()
let safeCount() =
let n = 1000000
let counter = ref 0
let spinlock = SpinLockClass()
let run i0 i1 () =
for i=i0 to i1-1 do
let locked = ref false
try
spinlock.Enter locked
if !locked then
counter := !counter + 1
finally
if !locked then
spinlock.Exit()
let thread = System.Threading.Thread(run 0 (n/2))
thread.Start()
run (n/2) n ()
thread.Join()
!counter发布于 2010-06-12 10:10:45
复制SpinLock结构的原因是!是一个函数:当将结构作为参数传递给函数或从函数返回时(或任何其他类型的赋值),结构都会被复制。但是,如果直接访问ref单元格的内容,则不会进行复制。
let safeCount() =
let n = 1000000
let counter = ref 0
let spinlock = ref <| SpinLock(false)
let run i0 i1 () =
for i=i0 to i1-1 do
let locked = ref false
try
spinlock.contents.Enter locked
if !locked then
counter := !counter + 1
finally
if !locked then
spinlock.contents.Exit()
let thread = System.Threading.Thread(run 0 (n/2))
thread.Start()
run (n/2) n ()
thread.Join()
!counter发布于 2010-06-11 10:06:05
SpinLock是一个值类型。当您取消引用spinLock变量(!spinLock)时,结构被复制,您进入/退出的锁现在不同了。
https://stackoverflow.com/questions/3019446
复制相似问题