https://msdn.microsoft.com/en-us/magazine/jj883956.aspx
Consider the polling loop pattern:
private bool _flag = true; public void Run() { // Set _flag to false on another thread new Thread(() => { _flag = false; }).Start(); // Poll the _flag field until it is set to false while (_flag) ; // The loop might never terminate! }In this case, the .NET 4.5 JIT compiler might rewrite the loop like this:
if (_flag) { while (true); }In the single-threaded case, this transformation is entirely legal and, in general, hoisting a read out of a loop is an excellent optimization. However, if the _flag is set to false on another thread, the optimization can cause a hang.
Note that if the _flag field were volatile, the JIT compiler would not hoist the read out of the loop. (See the “Polling Loop” section in the December article for a more detailed explanation of this pattern.)
如果我锁定 _flag,JIT 编译器是否仍会像上面显示的那样优化代码,或者只会使其 volatile 停止优化?
Eric Lippert 对 volatile 的评价如下:
Frankly, I discourage you from ever making a volatile field. Volatile fields are a sign that you are doing something downright crazy: you're attempting to read and write the same value on two different threads without putting a lock in place. Locks guarantee that memory read or modified inside the lock is observed to be consistent, locks guarantee that only one thread accesses a given chunk of memory at a time, and so on. The number of situations in which a lock is too slow is very small, and the probability that you are going to get the code wrong because you don't understand the exact memory model is very large. I don't attempt to write any low-lock code except for the most trivial usages of Interlocked operations. I leave the usage of "volatile" to real experts.
总结一下:谁保证上面提到的优化不会破坏我的代码? 只有 volatile?还有 lock 声明?还是别的?
既然 Eric Lippert 不鼓励您使用 volatile,那么一定还有其他东西吗?
反对者:我感谢对这个问题的每一个反馈。特别是如果你不赞成它,我想听听你为什么认为这是一个糟糕的问题。
bool 变量不是线程同步原语:这个问题是一个一般性问题。什么时候编译器不做优化?
Dupilcate:这个问题明确是关于优化的。您链接的那个没有提到优化。
最佳答案
让我们回答被问到的问题:
Will the JIT compiler still optimize the code as shown above if I lock _flag or will only making it volatile stop the optimization?
好吧,我们不回答被问到的问题,因为那个问题太复杂了。让我们把它分解成一系列不太复杂的问题。
Will the JIT compiler still optimize the code as shown above if I lock _flag?
简短回答:lock 比 volatile 提供了更强的保证,所以不,不允许抖动解除读取如果在 _flag 的读取周围有锁,则循环。当然锁也必须围绕着写。锁只有在您随处使用时才有效。
private bool _flag = true;
private object _flagLock = new object();
public void Run()
{
new Thread(() => { lock(_flaglock) _flag = false; }).Start();
while (true)
lock (_flaglock)
if (!_flag)
break;
}
(当然,我注意到这是一种等待一个线程向另一个线程发出信号的非常糟糕的方式。永远不要坐在一个紧密的循环中轮询标志!使用等待句柄像一个明智的人。)
You said locks were stronger than volatiles; what does that mean?
读取 volatiles 会阻止某些操作及时移动。写入 volatiles 会阻止某些操作及时移动。锁可以防止更多 操作被及时移动。这些预防语义称为“内存栅栏”——基本上,volatiles 引入了半栅栏,锁引入了全栅栏。
有关详细信息,请阅读有关特殊副作用的 C# 规范部分。
一如既往,我会提醒您, volatile 不能为您提供全局新鲜度保证。在多线程 C# 编程中没有变量的“最新”值这样的东西,因此 volatile 读取不会为您提供“最新”值,因为它不存在。存在“最新”值的想法意味着始终观察到读取和写入在时间上具有全局一致的顺序,这是错误的。线程仍然可以不同意 volatile 读取和写入的顺序。
Locks prevent this optimization; volatiles prevent this optimization. Are those the only thing which prevents the optimization?
没有。您还可以使用 Interlocked 操作,或者您可以显式引入内存栅栏。
Do I understand enough of this to use
volatilecorrectly?
没有。
What should I do?
首先不要编写多线程程序。一个程序中的多个控制线程不是一个好主意。
如果必须,不要跨线程共享内存。将线程用作低成本进程,并且仅在您有可以执行 CPU 密集型任务的空闲 CPU 时才使用它们。对所有 I/O 操作使用单线程异步。
如果您必须跨线程共享内存,请使用可用的最高级别编程结构,而不是最低级别。使用 CancellationToken 表示在异步工作流的其他地方取消的操作。
关于c# - .NET JIT 编译器可变优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52591453/
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
是否有适用于Ruby语言的.NETFramework编译器?我听说过DLR(动态语言运行时),这是否将使Ruby能够用于.NET开发? 最佳答案 IronRuby是Microsoft支持的项目,建立在动态语言运行时之上。 关于.net-是否有Ruby.NET编译器?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/199638/
有没有一种简单的方法来测试一个对象是不可变的(数字,零)还是不可变的(数组,哈希,对象)?换句话说,是否可以通过其他代码的副作用更改它?动机:我想创建一个版本化的值存储,但有些数据是数组。一些数组将存储自定义对象,我可以通过存储“in”属性并搜索它来反转关系。但我也希望能够存储符号数组、其他数组等。 最佳答案 我发现了一个低效的方法:classObjectdefprimitive?beginself.dupfalserescueTypeErrortrueendendend 关于ruby-
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭10年前。ImprovethisquestionLinux专家正在转向Mac(10.8)。因为我懒...我使用MacPorts安装MacVim。它似乎安装没有错误。我只需要mvim中的python、ruby和perl支持。$/opt/local/bin/mvim--version|egrep'patches|python|ruby|perl'Includedpatches:1-244,246-646+multi_lang-mzscheme+
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用