vto*_*ola 7 .net multithreading
我有一些问题需要澄清.
易失性读取确保您读取变量的最新值.这是否意味着它强制所有CPU刷新该变量的缓存值?只有那个变量或全部?因此,如果它将强制所有CPU刷新缓存的写入并从主内存获取最新版本,这是一个内存屏障吗?
易失性写入确保您为主存储器中的变量写入值.这是否意味着它会使所有CPU中该变量的所有缓存值都无效?
使用关键字volatile时使用内存屏障?
Interloked在原子操作中执行读/修改/写入.Interlocked是否确保您例如递增最新版本的变量,而其他CPU将看到此更改?我想是因为它应该使用内存屏障,但我不确定.那么我们可以说Interloked是原子地进行VolatileRead/modify/VolatileWrite吗?
当您使用内存屏障时,它是否会影响所有CPUS中的所有变量,或仅影响周围的变量?
锁定是昂贵的,因为如果线程必须等待,它会导致两个内存屏障和"上下文切换",但是Interlocked的优势是什么?只是为了避免"上下文切换"?
ReaderWriterLockSlim和递归有什么关系?我没有说明问题是什么.
正如你所看到的,我现在脑子里一团糟.
提前致谢.
在回答你的问题之前,我应该指出,内存障碍不仅仅影响CPU.应用程序运行时,实际上有两种内存模型在运行.一个是硬件级别,另一个是软件级别.作为开发人员,您必须编写两者中不同元素的最弱组合.使用CLR和x86架构,这通常意味着CLR更重要,因为x86架构实际上具有相当强大的内存模型.换句话说,volatile
关键字和其他内存屏障机制也将影响JIT如何生成代码.
1.易失性读取确保您读取变量的最新值.这是否意味着它强制所有CPU刷新该变量的缓存值?只有那个变量或全部?因此,如果它将强制所有CPU刷新缓存的写入并从主内存获取最新版本,这是一个内存屏障吗?
首先,从技术上讲,易失性读取不能确保您读取变量的最新值.它实际上意味着在volatile之前不会发生其他读或写.但是,效果是如果前面有另一个易失性读取,则读取必须来自主存储器.其次,不,易失性读取对其他写入没有影响,因此它不会强制所有CPU刷新其写入缓存.第三,是的,挥发性操作被认为是记忆障碍.
2.易失性写入确保您为主存储器中的变量写入值.这是否意味着它会使所有CPU中该变量的所有缓存值都无效?
与易失性读取类似,易失性写入在技术上与订购有关.它确保在volatile之后不会发生其他读或写.这并不意味着立即提交有问题的写入.它只影响执行该线程的CPU.有趣的是,x86架构实际上将所有写入视为易失性.但是,CLR没有(至少是ECMA规范).这就是为什么你仍然需要在写入时使用volatile操作.这是从硬件和软件级别编码最弱的存储器模型元素的一个示例.
3.使用关键字volatile时是否使用了内存屏障?
是.有两种类型的记忆障碍.全围栏和半围栏.半栅栏可以保证获取语义(易失性读取)或释放语义(易失性写入),但不能同时获得两者.完整的围栏(Thread.MemoryBarrier
例如通过)保护两者.
4.Interloked在原子操作中执行读/修改/写入.Interlocked是否确保您例如递增最新版本的变量,而其他CPU将看到此更改?我想是因为它应该使用内存屏障,但我不确定.那么我们可以说Interloked是原子地进行VolatileRead/modify/VolatileWrite吗?
是的.值得一提的是,可以使用CAS操作实现互锁增量和减量操作.在.NET中,您将Interlocked.CompareExchange
在循环中使用该方法,直到操作成功.我打赌,Interlocked.Increment
和Interlocked.Decrement
方法使用本机CPU指令,但我准备错了.
5.当您使用内存屏障时,它是否会影响所有CPUS中的所有变量,或仅影响周围的变量?
它将影响所有内存访问,但仅限于执行该线程的CPU.
6.锁定是昂贵的,因为它会导致两个内存屏障和一个"上下文切换",如果线程必须等待,但那么Interlocked的优势是什么?只是为了避免"上下文切换"?
是的,基本上.线程永远不会阻塞互锁操作.
7.与ReaderWriterLockSlim和递归有什么关系?我没有说明问题是什么.
在没有首先释放它的情况下,您无法在同一个线程上获取锁定两次.有关Joe Duffy博客的更多信息.