代码之家  ›  专栏  ›  技术社区  ›  SqlRyan

当联锁类可用时,为什么在.NET中使用SyncLocks进行简单操作?

  •  9
  • SqlRyan  · 技术社区  · 15 年前

    我在vb.net中做简单的多线程已经有一段时间了,并且刚刚进入我的第一个大型多线程项目。我总是用 Synclock 因为我觉得没有更好的方法。

    我刚知道 Interlocked 类-它使它看起来好像所有这些:

    Private SomeInt as Integer
    Private SomeInt_LockObject as New Object
    
    Public Sub IntrementSomeInt
        Synclock SomeInt_LockObject
            SomeInt += 1
        End Synclock
    End Sub
    

    可替换为单个语句:

    Interlocked.Increment(SomeInt)
    

    这将在内部处理所有锁定并修改数字。这将比为简单操作编写自己的锁简单得多(运行时间更长或更复杂的操作显然仍然需要自己的锁)。

    当我可以使用 互锁的 方法?

    5 回复  |  直到 12 年前
        1
  •  9
  •   SLaks    15 年前

    你是对的; Interlocked 应该在这里使用,而且比 SyncLock .
    然而, 互锁的 这个班不出名。

    但是,有些情况下需要使用 同步时钟 互锁的 不会有帮助的。

        2
  •  5
  •   ChaosPandion    15 年前

    这是因为没人知道。传播信息!

        3
  •  4
  •   Community CDub    7 年前

    简短的回答是因为 Monitor 锁(锁) SyncLock 在VB中 lock { } 在c)中,它不仅确保一次只有一个线程可以访问变量(或者严格地说,一次只有一个线程可以获得锁定对象上的锁),而且还创建了所需的内存屏障,以确保对变量的读取不会被优化掉。

    如果您从未简单地读取变量的值(换句话说,您的所有工作都是通过调用 Interlocked ),那你就没事了。但是,如果您需要能够执行变量的正常读取,则情况会更复杂。无锁读/写通常使用 volatile 关键字。这将指示编译器在使用变量的任何地方读取该变量的值,而不是将这些读取优化到本地缓存中。不幸的是,在vb.net中没有等价物,所以您必须使用其他东西。

    公认的答案 this question 应该提供更多关于你能做什么的信息。简而言之,大多数人使用 小精灵 在vb.net中,因为它比执行它所需的逻辑更简单、更简单 没有 同步时钟 .

        4
  •  2
  •   Janis H    12 年前

    我曾经读过一篇关于所谓的非原子和原子(在vb中:互锁)操作的很好的解释,并试图总结一下。

    Normal "non-atomic" operations consist of several steps 
    

    ->其他线程可以在这些streps之间工作

    "Atomic" operations consist of one only one step 
    

    ->处理原子操作时,其他线程无法执行工作,原子操作始终作为整体处理

    联锁类是这样的原子操作的集合,因此根据定义是线程安全的。 即使多个线程对同一个变量执行读写操作,这些操作也绝对是线程安全的。

    这些线程安全命令的组合仍然是不安全的,因为原子操作之间可能会出现竞争条件。

    因此,如果您想比较两个变量,然后增加较小的一个,这不是线程安全的,即使它们自己的单个操作是(interlocked.compare,interlocked.increment)。 在这里你仍然需要使用同步锁。

    除此限制外,互锁不存在“隐藏的不良一面”。

    a=5的外消旋条件的一个例子:

     Thread1: a+=1
     Thread2: a+=2    
     --> supposed to be 8, but can be only 6 or 7,
     but can also be 6 or 7 depending on which thread wins the race
    

    选项1:

    T1 step 1: read 5
    T1 step 2: add 1 = 6
    T1 step 3: write 6
    T2 step 1: read 6
    T2 step 2: add 2 = 8
    T2 step 3: write 8
    --> is 8 as supposed
    

    或选项2:

    T1 step 1: read 5
    T2 step 1: read 5
    T1 step 2: add 1 = 6
    T2 step 2: add 2 = 7
    T2 step 3: write 7
    T1 step 3: write 6
    --> is only 6
    

    或选项3:

    T1 step 1: read 5
    T2 step 1: read 5
    T1 step 2: add 1 = 6
    T2 step 2: add 2 = 7
    T1 step 3: write 6
    T2 step 3: write 7
    --> is only 7
    

    带联锁增量:

    选项1:

    T1 step 1: read 5, add 1, write 6
    T2 step 1: read 6, add 2, write 8
    

    或选项2:

    T2 step 1: read 5, add 2, write 7
    T1 step 1: read 7, add 1, write 8
    

    ->在所有情况下,假设A=8,线程安全解决方案

    在这里发布的所有问题都可以通过将这个简单的示例应用于可疑代码来解决。

    希望这能帮助其他人谷歌这个话题。 贾尼斯

        5
  •  1
  •   Henk Holterman    15 年前

    Interlocked 仅限于对整数、长和布尔值等进行简单操作。

    例如,如果要将项目添加到共享列表(t),则仍需要 SynClock .