MemoryBarrier方法
查了下MSDN的解释:
MemoryBarrier is required only on multiprocessor systems with weak memory ordering (for example, a system employing multiple Intel Itanium processors).
Synchronizes memory access as follows: The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.
就是说多核处理器会对运行CPU指令顺序重排优化,MemoryBarrier可以阻止指令重排,调用Thread.MemoryBarrier()之后的代码中内存访问不能再这之前就完成了。也就是它可以限制指令重排和内存读写的缓存。
下面有段代码,在release编译情况下会死循环(debug应该是没做instructions reorder而不会有问题)
bool complete = false;
var t = new Thread(() =>
{
bool toggle = false;
while (!complete)
toggle = !toggle;
});
t.Start();
Thread.Sleep(1000);
complete = true;
t.Join();
问题原因:
1.编译器、CLR或者CPU可能重新排序了程序指令,以此提高效率。
2.编译器、CLR或者CPU引入缓存优化导致其他的线程不能马上看到变量值的更改。
尝试了下将Thread.MomoryBarrier加到while中,保证complete读到的最新的:
此例子中MomoryBarrier 应该时解决jit时过度优化,虽然两个核心cache line 不会及时同步,complete 值修改通过MSIE协议也很快的通知到其他核心。
出现死循环在于jit 任魏complete值一直是false,并没有执行load操作,而是直接判断true跳转。
bool complete = false;
var t = new Thread(() =>
{
bool toggle = false;
while (!complete)
{
Thread.MemoryBarrier();
toggle = !toggle;
}
});
t.Start();
Thread.Sleep(1000);
complete = true;
t.Join(); 在看一个例子:(来自《window 并发编程指南》内存模型部分)MyObject mo= ..;int f= mo.field;if(f==0){ //same operation Console.WriteLine(f);}如果mo.field 在读取和Console.WriteLine相隔足够远,那么编译器可能会认为读mo.field 读取两遍会更有效,被编译成如下代码:
MyObject mo= ..;if(mo.filed==0){ //same operation Console.WriteLine(mo.field);}
编译器可能判断,保留这个值是否给寄存器带来压力并导致栈空间的低效使用,并且之个分支是否很少被使用(因此f值就不需要多次)这样带来多线程问题,将f值使用volatitle修饰,可禁止这种优化
转载于:https://www.cnblogs.com/lulu/archive/2012/05/26/2519580.html
MemoryBarrier方法相关推荐
- 第二节:深入剖析Thread的五大方法、数据槽、内存栅栏
一. Thread及其五大方法 Thread是.Net最早的多线程处理方式,它出现在.Net1.0时代,虽然现在已逐渐被微软所抛弃,微软强烈推荐使用Task(后面章节介绍),但从多线程完整性的角度上来 ...
- 【转】1.3异步编程:线程同步基元对象
开始<异步编程:同步基元对象(上)> 示例:异步编程:线程同步基元对象.rar 如今的应用程序越来越复杂,我们常常需要多线程技术来提高我们应用程序的响应速度.每个线程都由自己的线程ID,当 ...
- 在 Oracle Enterprise Linux 和 iSCSI 上构建您自己的 Oracle RAC 11g 集群
作者:Jeffrey Hunter 了解如何以低于 2,700 美元的费用在 Oracle Enterprise Linux 上安装并配置 Oracle RAC 11g 第 2 版开发集群. 本指南中 ...
- Java面试题大全2021版
一.Java 基础 JDK 和 JRE 有什么区别? JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境. JRE:Java Run ...
- 【转】细说.NET中的多线程 (六 使用MemoryBarrier,Volatile进行同步)
上一节介绍了使用信号量进行同步,本节主要介绍一些非阻塞同步的方法.本节主要介绍MemoryBarrier,volatile,Interlocked. MemoryBarriers 本文简单的介绍一下这 ...
- Lock,LockFree,MemoryBarrier,ConcurrentCollection
最近看并行编程书本的一些心得,简单记录下多线程和并行编程必知必会的几个概念,再次加深自己的理解. .NET Framework4提供了一个新的命名空间System.Collections.Concur ...
- Kotlin协程使用,协程使用注意事项,协程中的await方法使用|不使用suspend使用协程
参见 码云 协程使用方法一 (Dispatchers调度器模式) 指定不同线程.同线程会挂起并阻塞(挂起是不影响主线程执行,阻塞是同样的IO线程会阻塞) withContext(Dispatchers ...
- IDEA中将代码块封装为方法,IDEA代码重构快捷键
IDEA中将代码块封装为方法 选中要转换的代码块,快捷键: Windows快捷键:Alt + Shift + M Mac快捷键:Alt + Command + M 如图:
- IDEA自动生成对象所有set方法
idea中有一款插件能够生成对象所有的set方法,GenerateAllSetter :下载地址 步骤1:将下载好的压缩包放在自己记得的文件夹中,在idea中进行导入 步骤2:在本地选中刚才的压缩包, ...
- List元素互换,List元素转换下标,Java Collections.swap()方法实例解析
Java Collections.swap()方法解析 jdk源码: public static void swap(List<?> list, int i, int j) {// ins ...
最新文章
- 400全集python全套视频教程-千锋出品全套python视频教程,400大全集,你了解吗?...
- python 斐波拉契递归 尾递归 备忘录 动态规划 迭代
- tensorflow环境下的识别食物_研究室秒变后厨,TensorFlow被馋哭!日本团队用深度学习识别炸鸡,救急便当工厂...
- mfc通过信号量保证线程同步
- JSON数据、字符串拼接、宽字符处理、数组、Notice警告、isset和empty、变量、作用域、常量、include和require
- 多容器,Nginx容器灵活切换PHP版本!同时运行多个PHP容器
- 【javascript】 的严格模式 详解
- cad中计算机的快捷键,CAD常用快捷键汇总
- android手机控制电视,类Siri语音控制技术 Android手机也能控制电视
- 火热的区块链技术,也能解决文化领域的这些痛点
- android旅游视频播放,VPlayer视频播放器
- 程序员到底有没有必要买一台阿里云服务器?
- Oracle 基本SQL语句
- hibernate配置映射的问题
- 11台计算机的英语,世界第一台计算机英文缩写名为
- C语言--数据在内存中的存储
- 聊城市普通话水平测试软件音频,聊城市普通话水平测试培训-聊城市教师教育网.ppt...
- cf服务器无响应,穿越火线优化玩家分辨率,告别白屏未响应!
- MATLAB中cla函数
- 六.实战——Excel表格的导入和导出