在
《C++0x漫谈》系列之:多线程内存模型 (简称为漫谈)解释了多线程并行的困难,在这里我分层地看看这个问题。
1.为什么分层次?
C++语言表达的抽象和机器的抽象距离比较近,而且几乎看不到C++在虚拟机上跑的实例,所以两者的关系容易混淆。有人常常把反汇编拿出来一看,并作为C++语言是如此的证据,这是本末倒置的。假定C++都是直接翻译为汇编,于是这只是一个如何将一个语言翻译为另外一个语言的问题。编译器干的事就是用目标语言的一些抽象来实现源语言一些抽象,所以目标语言的语义,行为,并不能决定源语言,而只能说明翻译的正确性和质量。比如,某个C++类在语义上有个构造函数的调用,但是其行为是平凡的,在翻译后的代码中看不到任何构造函数调用的代码,这并不是构造函数不存在的证据。所以,这里我们分出层次,一方面是汇编及其实现(即CPU)的结合体,另一方面就是C++了。
2.怎么翻译?
2.1[汇编语言的语义]如果不考虑较高层次的汇编(比如宏汇编)因为其中添加了一些东西,使得更抽象。只考虑一些常见的指令,由于汇编本身就描述了一些操作步骤,在操作过程中对环境进行改变,从一个状态转换到另一个状态,所以其操作语义和语言没什么大的间隙。如果考虑多个核在同一个环境下执行代码,intel(这里只谈x86)也定义了其memory order,其中展示了一些并行执行的汇编代码,并说明什么样的结果是可能的,什么样的结果是不可能的,以一种晦涩的方式说明了多个执行单元同时执行时执行环境的状态变化情况,换句话说,定义了语义。
1.为什么分层次?
C++语言表达的抽象和机器的抽象距离比较近,而且几乎看不到C++在虚拟机上跑的实例,所以两者的关系容易混淆。有人常常把反汇编拿出来一看,并作为C++语言是如此的证据,这是本末倒置的。假定C++都是直接翻译为汇编,于是这只是一个如何将一个语言翻译为另外一个语言的问题。编译器干的事就是用目标语言的一些抽象来实现源语言一些抽象,所以目标语言的语义,行为,并不能决定源语言,而只能说明翻译的正确性和质量。比如,某个C++类在语义上有个构造函数的调用,但是其行为是平凡的,在翻译后的代码中看不到任何构造函数调用的代码,这并不是构造函数不存在的证据。所以,这里我们分出层次,一方面是汇编及其实现(即CPU)的结合体,另一方面就是C++了。
2.怎么翻译?
显然,翻译建立在对两种语言上的充分理解上。理解一个语言,就要理解其提供的抽象及其语义。如何定义语义?这是研究程序设计语言的人干的,比较经典的有操作语义,指称语义。在这里我们不严格地从操作语义的角度来看这两种语言。
根据维基的描述:一个计算机语言的操作语义描述一段合理的程序是怎样被理解为一系列计算机步骤的。这些步骤就是这个程序的意义。
2.1[汇编语言的语义]如果不考虑较高层次的汇编(比如宏汇编)因为其中添加了一些东西,使得更抽象。只考虑一些常见的指令,由于汇编本身就描述了一些操作步骤,在操作过程中对环境进行改变,从一个状态转换到另一个状态,所以其操作语义和语言没什么大的间隙。如果考虑多个核在同一个环境下执行代码,intel(这里只谈x86)也定义了其memory order,其中展示了一些并行执行的汇编代码,并说明什么样的结果是可能的,什么样的结果是不可能的,以一种晦涩的方式说明了多个执行单元同时执行时执行环境的状态变化情况,换句话说,定义了语义。