c# - Interlocked.CompareExchange 在 dapper .net 方法中用于什么?

标签 c# .net thread-safety dapper

Link.TryAdd方法的dapper代码中,有如下一段代码:

var snapshot = Interlocked.CompareExchange(ref head, null, null);

为什么这是必需的而不是简单的:

var snapshot = head;

这两行都没有改变head的值,两行都将head的值赋值给snapshot。为什么选择第一个而不是第二个?

编辑:我指的代码在这里:https://github.com/SamSaffron/dapper-dot-net/blob/77227781c562e65c167bf7a933d69291d5bdc6f3/Dapper/SqlMapper.cs

最佳答案

他们想要进行 volatile 读取,但是没有采用通用类型参数的 Thread.VolatileRead 重载。以这种方式使用 Interlocked.CompareExchange 可获得相同的结果。

他们试图解决的问题是,JIT 编译器可以在认为合适的情况下优化对 temp 的赋值。如果当前线程在一系列操作中使用 head 引用时另一个线程改变了 head 引用,这可能会导致线程问题。

编辑:

问题不在于在 TryAdd 开始时读取了过时值。问题是在第 105 行,他们需要将当前头部与之前的头部进行比较(保存在 snapshot 中)。如果有优化,则没有保存先前值的 snapshot 变量,此时会再次读取 head 。即使 head 可能在第 103 行和第 105 行之间发生变化,CompareExchange 也很有可能成功。结果是如果两个线程同时调用 TryAdd,列表中的节点将丢失.

关于c# - Interlocked.CompareExchange 在 dapper .net 方法中用于什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11110012/

相关文章:

c# - 在继承的 UserControl 中通过 Designer 编辑 DataGridView

c# - 将十六进制颜色转换为整数

c++ - 编写 C++ Dll 并将其高效地公开给 .NET(不通过 C++/CLI)

c# - 如何隐藏 asp :Table? 中的列

java - CompletableFuture 成功 join() 设置字段后,字段是否保证一致?

c# - 为什么 Enumerable.Empty() 返回一个空数组?

c# - unity PerThreadLifetimeManager 和任务

.net - 全局属性 'http://www.w3.org/XML/1998/namespace:lang' 已经声明

java - 当有多个线程时,跳出循环的最佳方法是什么?

c# - AddOrUpdate-ing 时锁定 ConcurrentDictionary?