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

关于线程同步的几个问题

  •  7
  • vtortola  · 技术社区  · 15 年前

    我有一些问题要澄清。

    1. Volatile read确保读取 变量的最新值。是吗 意味着它强制所有的CPU 为此刷新缓存的值 变数?只有那个变量还是全部? 所以如果它能强迫所有CPU 刷新缓存的写入并获取最新的 主存储器中的版本,这是 记忆障碍?

    2. Volatile write确保 main中变量的值 记忆。是否意味着它无效 所有的缓存值 所有CPU中的变量?

    3. 当你使用记忆屏障时 你用的关键字是volatile?

    4. 插话表演 读取/修改/写入原子 操作。联锁是否确保 你就是个例子 递增最新版本的 变量和其他CPU将看到 这个零钱?我想是因为 应该用记忆屏障, 但我不确定。所以我们可以说 插话的意思是 挥发物读取/修改/挥发物写入 原子的?

    5. 当你使用记忆屏障时 它影响到所有变量 CPU,还是只是周围的CPU?

    6. 锁是昂贵的,因为它 导致两个记忆障碍和 如果线程有 等等,但是 联锁的优点?只是为了 避免“上下文切换”?

    7. 怎么回事 ReaderWriterLockSlim和 递归性?我不明白 有什么问题。

    如你所见,我现在脑子里乱七八糟的。

    提前谢谢。

    2 回复  |  直到 15 年前
        1
  •  7
  •   Brian Gideon    11 年前

    在回答你的问题之前,我应该指出内存障碍不仅仅影响CPU。当应用程序运行时,实际上有两个内存模型在运行。一个在硬件层,另一个在软件层。作为一名开发人员,您必须为这两种元素中最弱的组合编写代码。对于CLR和x86体系结构,这通常意味着CLR更重要,因为x86体系结构实际上具有相当强的内存模型。换句话说 volatile 关键字和其他内存屏障机制也会影响JIT生成代码的方式。

    1.Volatile read确保读取变量的最新值。是吗 意味着它强制所有的CPU 为此刷新缓存的值 变数?只有那个变量还是全部? 所以如果它能迫使所有的CPU 缓存写入并获取最新版本 从主存储器,这是存储器吗 障碍?

    首先,从技术上讲,volatile read不能确保读取变量的最新值。这实际上意味着在易失性读写之前,没有其他读写操作可以发生。但是,其结果是,读取必须来自主内存 如果 前面是另一个volatile read。其次,不,易失性读取对其他写入没有影响,因此它不会强制所有CPU刷新其写缓存。第三,是的,易失性操作被认为是内存障碍。

    2.Volatile write确保向主存储器中的变量写入一个值。 它是否意味着它将 该变量的缓存值 CPU?

    与volatile read类似,volatile write在技术上是关于排序的。它确保在易失性读写之后不会发生其他读写操作。这并不意味着所讨论的写操作会立即被提交。它只影响执行该线程的CPU。有趣的是,x86架构实际上处理 全部的 作为易失性写入。但是,CLR没有(至少是ECMA规范)。这就是为什么您仍然必须对写操作使用volatile操作的原因。这是从硬件和软件两个层面为最弱的内存模型元素编码的一个例子。

    3.在使用关键字volatile时,是否使用了内存屏障?

    对。有两种类型的记忆障碍。全篱笆和半篱笆。半隔离可以获取语义(volatile read)或释放语义(volatile write),但不能同时获取语义和释放语义。满篱笆 Thread.MemoryBarrier 例如)两者都保证。

    4.interlocked在原子中执行读/修改/写操作 操作。联锁是否确保 例如,你正在增加 变量的最新版本 其他CPU会看到这个变化吗?我 这么想是因为它应该 记忆障碍,但我不确定。所以 我们能说Interoked在做什么吗 挥发物读取/修改/挥发物写入 原子的?

    是的。对于值得联锁的增量和减量操作,可以使用 CAS 行动。在.NET中,您将使用 Interlocked.CompareExchange 方法,直到操作成功为止。我打赌 Interlocked.Increment Interlocked.Decrement 方法使用的是本机CPU指令,但我已经准备好犯错了。

    5.当你使用内存屏障时,它是否会影响所有变量 CPU,还是只是周围的CPU?

    它将影响所有内存访问,但仅限于执行该线程的CPU。

    6.锁定代价高昂,因为它会导致两个内存屏障和一个 如果线程必须 等等,那有什么好处呢 联锁的?只是为了避免 “上下文切换”?

    基本上是的。线程从不通过互锁操作阻塞。

    7.ReaderWriterLockSlim和递归性有什么关系? 我不明白是什么问题。

    如果不先释放锁,则不能在同一线程上获取两次锁。有更多关于 Joe Duffy's blog .

        2
  •  1
  •   supercat    15 年前

    锁的一个问题是,任何获取锁的线程都必须承担其他线程在任意时间段内持有锁的风险。保证Threading.Interlocked.CompareExchange调用几乎立即返回(无论是否成功);除非在故意激烈竞争的情况下,否则 短的 CompareExchange自旋锁也将快速返回。如果一个线程获取一个锁,然后在释放它之前离开并执行其他操作,那么其他线程将不得不等待这些其他操作完成,然后才能获取该锁。CabExchange自旋锁不存在这样的危险。除非其他线程主动命中spinlock本身,否则spinlock将很快完成。