.NET 4 SpinLock

Jon*_*rop 5 .net f#

以下测试代码(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
Run Code Online (Sandbox Code Playgroud)

我希望SpinLock相互排除计数器,因此,它返回1,000,000的计数,但相反,它返回较小的值,好像没有发生互斥.

有什么想法有什么不对吗?

Ste*_*sen 10

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
Run Code Online (Sandbox Code Playgroud)


Dmi*_*mov 8

SpinLock是一种值类型.当你取消引用你的spinLock变量(!spinLock)时,结构被复制了,你输入/退出的锁现在是不同的.


Guv*_*nte 3

编辑: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
Run Code Online (Sandbox Code Playgroud)