基于 C# 7 元组的变量交换线程安全吗? [英] Is a C# 7 tuple-based variable swap thread safe?

查看:47
本文介绍了基于 C# 7 元组的变量交换线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Before C# 7's tuples, the standard way to swap two variables was something like:

var foo = 5;
var bar = 10;

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

但是现在我们可以使用

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

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

It's on one line and it's prettier. But is it thread safe - is the swap done atomically, or is this just sugar over top of a multi-step operation?

推荐答案

不,基本上".

ValueTuple<...> 系列是可变值类型,这使得它变得复杂.旧的 Tuple<...> 家族是不可变的引用类型;不可变"很重要,因为这意味着它不会改变单个字段 - 它正在创建一个具有所有值的新对象.引用类型"很重要,因为这是一个单一的引用交换, 是线程安全的,因为您无法获得撕裂的引用".它在其他方面不是线程安全的:没有关于排序或寄存器等的保证.

The ValueTuple<...> family are mutable value types, which makes it complex. The older Tuple<...> family were immutable reference types; the "immutable" matters because it means it isn't changing individual fields - it is creating a new object with all the values. The "reference-type" matters because this is then a single reference exchange which is thread-safe in as much as you can't get a "torn reference". It isn't thread-safe in other ways: there's no guarantees about ordering or registers, etc.

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

But with ValueTuple<...> even that is gone. Because it is a mutable type, this is most likely implemented as multiple ldloca/ld.../stfld instructions, so even if the value type is not larger than the CPU width, there's no guarantee that it will all be written in a single CPU instruction - and it almost certainly won't be. In the "return a value, assign the entire thing" scenario it might be a single CPU instruction if small enough, but it might not! To make it even more complex, in addition to the mutable field approach, there are also custom constructors - but they will still ultimately be writing over the same memory location (for value types, the destination managed reference is passed into the constructor, rather than the constructed value being passed out).

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

There is no guarantee whatsoever made by the language or runtime about tuple atomicity; they only make guarantees about references and certain primitives -additionally, even if it was: thread-safety is a lot more than just atomicity.

最后,它依赖于目标 CPU;显然 2-int 元组不能在 32 位 CPU 上是原子的.

Finally, it would also depend don the target CPU; obviously a 2-int tuple cannot be atomic on a 32-bit CPU.

这篇关于基于 C# 7 元组的变量交换线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆