在for循环中执行空while循环是否安全?

时间:2016-03-07 17:11:03

标签: c#

我很好奇在for循环中做一个空的while循环是否安全,为了阻止它继续直到x为真?

例如(更新到下载示例):

string[] links = new string[3] {"http://url.com/download1.rar", "http://url.com/download2.rar", "http://url.com/download3.rar"};

public void download(String link) {
   // download link
   x = false;
}

然后在某个地方

for (int i; i < links.length; i++) {
   download(links[i]);
   x = true;
   while (x) {
     // Do nothing so the for loop basically freezes until download is finished
   }

   // Do something else or just end it here and continue the loop
}

请注意:这是一个简单的例子,下载与问题完全无关,我只是想帮助你理解这个问题

还是有更好的方法可以做到这一点吗?

编辑:编辑代码以显示我正在思考的更好的例子

2 个答案:

答案 0 :(得分:3)

编辑:更新完全改变了问题。

如果您要更新循环中的x并且未从外部线程更改,则您的程序将锁定并且不会继续,因为您的代码无法访问x = true,因为它是被while循环阻止。

这会占用100%的CPU在单个核心上执行0个有用的工作,你认为可以吗?此外,如果x未标记为volitile,即使您更新x,它也可能永久旋转。

更好的方法是使用某种互斥锁来阻止代码直到你准备好。例如ManualResetEventSlim

private ManualResetEventSlim _block = new ManualResetEventSlim();

public void A()
{
    for (int i; i < args.length; i++) 
    {
       _block.Wait(); //This code blocks till UnblockA() is called.

       // Do something
    }
}

public void UnblockA()
{
    _block.Set();
}

public void BlockA()
{
    _block.Reset();
}

答案 1 :(得分:1)

直接回答你的问题:不,这不是普遍安全的。请参阅这篇关于.NET中线程的优秀文章中的“内存障碍和易失性”一节:http://www.albahari.com/threading/part4.aspx#_Memory_Barriers_and_Volatility

具体做法是:

“我们真的需要锁和障碍吗?

使用没有锁或围栏的共享可写字段会遇到麻烦。关于这个主题有很多误导性的信息 - 包括MSDN文档,该文档指出仅在内存排序较弱的多处理器系统上需要MemoryBarrier,例如采用多个Itanium处理器的系统。我们可以通过以下简短程序证明内存屏障在普通的英特尔酷睿2和奔腾处理器上非常重要。您需要在启用优化且没有调试器的情况下运行它(在Visual Studio中,在解决方案的配置管理器中选择Release Mode,然后在不调试的情况下启动):

static void Main()
{
  bool complete = false; 
  var t = new Thread (() =>
  {
    bool toggle = false;
    while (!complete) toggle = !toggle;
  });
  t.Start();
  Thread.Sleep (1000);
  complete = true;
  t.Join();        // Blocks indefinitely
}

此程序永远不会终止,因为完整变量缓存在CPU寄存器中。在while循环中插入对Thread.MemoryBarrier的调用(或锁定读取完成)可以修复错误。“

后来:

“实际上,英特尔的X86和X64处理器始终对读取和释放禁用写入 - 无论您是否使用volatile关键字 - 因此如果您使用此关键字对硬件没有影响但是,volatile会对编译器和CLR以及64位AMD和(在更大程度上)Itanium处理器上执行的优化产生影响。这意味着你不能因为你的处理器而放松一下。客户端运行特定类型的CPU。

(即使你确实使用了挥发性物质,你仍应保持健康的焦虑感,我们很快就会看到!)“