方法调用语句是按照它们的写入顺序同步执行的吗?

时间:2013-12-04 17:52:10

标签: c#

例如:

void Function1()
{
  Function2();
  Function3();
}

Function3是否会保证等到Function2完成每次Function1被调用后才会处理?

4 个答案:

答案 0 :(得分:5)

是。 Function3()等待,直到Function2()执行完成为止。

如果您想独立调用它们,可以使用Multi-Threading概念。

使用Task的评论中的建议

编辑远远优于Thread,因为它是higher level概念。

Task Vs Thread

尝试这个以独立方式调用它们:

using System.Threading.Tasks;

static void Main(String[] args)
        { 
            Task t1 = new Task(Function2);
            Task t2 = new Task(Function3);
            t1.Start();
            t2.Start();
        }

这里我们无法保证执行流程如何继续。因为它们独立运行。

答案 1 :(得分:2)

我不完全清楚“完成处理”是什么意思。

但只有在Function3() 返回之后才会调用Function2(),这就是imperative programming背后的整个想法,而基本的C#是一种命令式语言。

答案 2 :(得分:2)

严格来说没有。现代CPU为了提高性能,在引擎盖下进行了大量的优化。它们并行执行,利用分支预测,流水线等,这样它们实际上可以启动甚至完成那些在实际尚未完成的事情之后发生的操作。

然而,您无需担心。我们非常痛苦地隐藏这些实现细节。虽然这些操作可能实际以给定的顺序发生,但您无法观察到它们无序的事实。换句话说,您可以始终确保执行该代码后计算机的最终状态将是按顺序执行语句时的状态。如果处理器选择不按顺序执行它们,它将永远不会导致程序的功能不同。

当然,正如评论中所说,这仅适用于单个线程的执行。当你有多个线程执行时,很少有关于观察到的每个操作的执行顺序的保证。

答案 3 :(得分:1)

C# language specification说:

  

3.10执行顺序

     

执行C#程序以使每个人的副作用   执行线程保留在关键执行点。在旁边   效果定义为易失性字段的读取或写入,写入a   非易失性变量,写入外部资源,以及   抛出一个例外。关键的执行点在哪里   必须保留这些副作用的顺序是参考   volatile字段(第10.5.3节),锁定语句(第8.12节)和线程   创建和终止。执行环境可以自由更改   执行C#程序的顺序,但有以下几点   约束:

     
      
  • 数据依赖性保留在执行的线程中。也就是说,计算每个变量的值,就像计算中的所有语句一样   线程以原始程序顺序执行。
  •   
  • 保留初始化排序规则(§10.5.4和§10.5.5)。
  •   
  • 关于易失性读写(第10.5.3节),保留了副作用的顺序。另外,执行环境   如果它可以推断出那个,那就不需要评估表达式的一部分   表达式的值未被使用,并且没有必要的副作用   生成(包括通过调用方法或访问方法引起的任何方法   易变场)。程序执行被中断时   异步事件(例如另一个线程抛出的异常),它   不保证可观察到的副作用是可见的   原始程序订单。
  •   

所以我认为这意味着如果编译器或抖动可以证明您的两个函数调用可以重新排序,甚至可以跳过,那么编译器可以自由地执行此操作。实际上,我认为编译器或抖动不会像代码那样执行优化,并且函数调用将同步执行。最重要的是,由于优化原因,CPU完全可以自由地重新排序执行,并且会这样做。当然,它不会以改变可观察输出的方式重新排序执行。

在任何情况下都有点没有意义,因为只要语言规范或CPU架构允许重新排序,只有在它对程序的含义没有任何影响时才允许。所以,你不能通过一个心理模型来说明任何伤害,这个模型说明语句是按顺序同步执行的。如果编译器和/或CPU选择重新排序,则会以不影响程序结果的方式执行此操作。