c#中的寄存器
本文关键字:寄存器 | 更新日期: 2023-09-27 18:08:33
我们都知道堆栈和堆的概念,但是我最近读到第三种保存数据的方法:寄存器。
我很难找到关于这种类型的好文章,我找到的是:http://www.dotnetperls.com/method-parameter,还有很多关于C的东西,例如:http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/
到目前为止,我唯一的真实信息是:每个CPU都有自己的寄存器,可以用来保存数据,可以以最快的方式访问,例如在for循环中。
据我所知,这个注册是由CLR完成的。然后我想起了这个volatile关键字,如果我们看一下MSDN:
volatile关键字表示字段可能被修改同时执行的多个线程。字段是声明的volatile不受编译器优化的影响假设只有一个线程访问。这保证了最最新的值在任何时候都出现在该字段中。
Volatile就是这样吗?它告诉CLR不使用CPU寄存器,而是使用堆栈/堆,所有CPU/线程都可以访问它?
"每个CPU都有自己的寄存器"
每个CPU都有一组寄存器,这些寄存器用于涉及任何数据的大多数操作。通常,一条指令将内存中的一些数据加载到寄存器中,然后另一条指令对寄存器中的数据进行一些计算。
CPU有一些寄存器用于存储数据,一些寄存器用于存储指针,还有一些特殊的寄存器用于跟踪程序的执行,如指令指针、堆栈指针和标志寄存器。
由于CPU有多个寄存器,JIT编译器有时可以使用其中几个寄存器作为局部变量的存储。寄存器不是在堆栈上分配变量,而是专门用来保存变量的值。
volatile
关键字不影响寄存器用于存储的方式。如果一个变量可以被不同的线程访问,那么它就不是应该存储在寄存器中的候选变量。实际上,它只是局部变量,范围有限,生命周期短,将存储在寄存器中。
这句话具有误导性,因为它没有准确定义volatile所保证的内容。在编译器优化方面没有指定Volatile。此外,在ARM上限制编译器是不够的。CPU也必须受到限制。我建议你研究一下volatile究竟保证了什么。
volatile甚至不能阻止寄存器的使用。Volatile加载保证Volatile变量被读取的频率和程序读取的顺序完全相同。
当你写:
volatile int sharedVar = 0;
Console.WriteLine(sharedVar);
Console.WriteLine(sharedVar);
JIT必须精确读取两次。但是它仍然可以使用寄存器来存储读取的值。
如果CLR可以证明sharedVar
从来没有被写入,并且总是有0
的值,它甚至可以删除读。它可能不得不在某些地方插入内存屏障而不是读取,因为volatile
访问有一定的顺序保证。但是根本不需要物理上的负荷。(当前的JIT不做这个优化)
寄存器是一个实现细节。CLR没有按照物理实现来指定。我理解你想了解实现细节,这很好。但是,对于CLR向程序员保证的内容来说,它们并不重要。