加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

.NET内存模型,易变量和测试集:什么是保证?

发布时间:2020-12-14 17:48:47 所属栏目:Java 来源:网络整理
导读:我知道.NET存储器模型(在.NET Framework;不是compact / micro / silverlight / mono / xna / what-have-you-you-you-you-you)保证了某些类型(最引人注目的是基本的整数和引用)操作被保证是原子. 此外,我相信x86 / x64测试和设置指令(和Interlocked.CompareEx
我知道.NET存储器模型(在.NET Framework;不是compact / micro / silverlight / mono / xna / what-have-you-you-you-you-you)保证了某些类型(最引人注目的是基本的整数和引用)操作被保证是原子.

此外,我相信x86 / x64测试和设置指令(和Interlocked.CompareExchange)实际上引用了全局内存位置,所以如果它成功了另一个Interlocked.CompareExchange会看到新的值.

最后,我相信volatile关键字是编译器传播read&写入ASAP并且不重新排序有关此变量的操作(对?).

这导致几个问题:

我的信仰是否正确?
> Interlocked.Read没有int的重载,只有longs(这是2个WORD,因此通常不会被原子读取).我总是假设.NET内存模型保证在读取int /引用时可以看到最新的值,但是使用处理器缓存,寄存器等.我开始看到这可能是不可能的.那么有办法强制变量被重新引用吗?
>为了解决整数和参考的上述问题,是否有足够的易失性?
>在x86 / x64我可以假设…

如果有两个全局整数变量x和y,两者都初始化为0,如果我写:

x = 1;
y = 2;

NO线程将看到x = 0和y = 2(即写入将按顺序发生).如果它们是挥发性的,这是否会改变?

解决方法

>只读取和写入最多32位宽的变量(x64系统上为64位宽)为原子.所有这一切意味着你不会读取一个int并获得一个半写的价值.这并不意味着算术是原子的.
>联锁操作也作为内存障碍,所以是的,Interlocked.CompareExchange会看到更新的值.
>见 this page. Volatile不意味着订购.一些编译器可能会选择不对易失性变量进行重新排序,但CPU可以自由重新排序.如果要停止CPU重新排序说明,请使用(全)内存屏障.
>内存模型确保读写是原子的,并且使用volatile关键字确保读取将始终来自内存而不是来自寄存器.所以你会看到最新的价值.这是因为x86 CPU会在适当时使缓存无效 – 参见 this和 this.另请参见 InterlockedCompareExchange64如何原子读取64位值.
最后,最后一个问题.答案是线程实际上可以看到x = 0和y = 2,并且使用volatile关键字不会改变,因为CPU可以自由地重新排序指令.你需要一个记忆障碍.

概要:

>编译器可以自由地重新排序指令.> CPU可以自由重新排序指令.>字大小的读写是原子的.算术和其他操作不是原子的,因为它们涉及读取,计算,然后写入.>从内存读取大小字体将始终检索最新的值.但大多数时候你不知道你是否真的从记忆中读书.>全记忆障碍停止(1)和(2).大多数编译器允许您自己停止(1).> volatile关键字确保你正在从内存中读取 – (4).>互锁操作(锁前缀)允许多个操作是原子的.例如,读写(InterlockedExchange).或者读取比较写(InterlockedCompareExchange).它们也作为记忆障碍,所以(1)和(2)被停止.他们总是写信(显然),所以(4)被保证.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读