c# - C# 7 基于元组的变量交换线程安全吗?

标签 c# thread-safety

在 C# 7 的元组之前,交换两个变量的标准方法如下:

var foo = 5;
var bar = 10;

var temp = foo;
foo = bar;
bar = temp;

但是现在我们可以使用

(foo, bar) = (bar, foo);

它在一条线上,而且更漂亮。但它是线程安全的吗?交换是原子完成的,还是这只是多步骤操作之上的糖衣?

最佳答案

“不,基本上”。

ValueTuple<...> family 是可变的值类型,这使得它变得复杂。老的Tuple<...> family 是不可变的引用类型; “不可变”很重要,因为它意味着它不会更改单个字段 - 它会使用所有值创建一个新对象。 “引用类型”很重要,因为这是一个单一的引用交换,它是线程安全的,因为你无法获得“撕裂的引用”。它在其他方面不是线程安全的:无法保证排序或寄存器等。

但与 ValueTuple<...>甚至那也消失了。因为它是可变类型,所以很可能实现为多个 ldloca/ld.../stfld指令,因此即使值类型不大于 CPU 宽度,也不能保证它将全部写入单个 CPU 指令中 - 而且几乎肯定不会。在“返回一个值,分配整个事物”场景中,如果足够小,它可能是单个CPU指令,但也可能不是!为了使其更加复杂,除了可变字段方法之外,还有自定义构造函数 - 但它们最终仍将写入相同的内存位置(对于值类型,目标托管引用被传递到构造函数中,而不是被传递到构造函数中。

语言或运行时不保证元组原子性;它们仅对引用和某些原语做出保证 - 另外,即使是:线程安全不仅仅是原子性。

最后,它取决于 objective-c PU;显然 2-int 元组不能在 32 位 CPU 上是原子的。

关于c# - C# 7 基于元组的变量交换线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48550397/

相关文章:

c# - 如何从 ResourceDictionary 设置 Button.Command?

c# - 系统.InvalidOperationException : Collection was modified

c++ - 制作 C++ 哈希表的最佳策略,线程安全

c# - 使类型的实例不可存储

c# - 如何在 C# 中将 Fedex 运输请求类型转换(或强制转换)为费率请求类型?

python - Django的 "Model"API线程安全吗?

c# - 从后台工作人员登录MyLogger时发生跨线程InvalidOperationException

java - 多线程异常处理释放资源

c# - FileNotFoundException 抛出时间太长,有没有办法缩短超时?

c# - 带按钮的 TreeView 多级自定义模板