关于并发语言的讨论

首先声明,我对并发的了解还是很肤浅的。但就目前的情况来说,这是一个迫切需要讨论的话题,也只有在有益的讨论中,才有可能让自己不再肤浅。所以我要在这个肤浅的基础上谈一点更加肤浅的看法,作为引玉之砖。

我看完Herb Sutter在《免费午餐已经结束——软件历史性地向并发靠拢》一文后的感觉是:

最为重要的方面是程序员需要改变自己的观念,把并发作为一种基本概念来掌握。其次才是语言需要对并发的支持。

这个重点大师已经说过了,我就不必再学舌,所以这里谈谈次要一些的语言问题。

在跟令狐讨论了一番之后,我认为语言的变化应该至少分成两类:一是类C语言,另外则是VM语言和动态语言。

先说C语言。令狐认为因为硬件模型已经变化到并发的时代,C语言增加并发特性是必须的,甚至可能是一种新的中级语言。这点我很赞同。但是孟岩所认为的“Java凭借java.util.concurrent就能够坐这个位置”,我觉得是不行的。除了我在《语言的缺陷》中所说过的原因以外,还有一点就是我们认为这种并发C语言并须将并发纳入语言的特性中,而不是用库的方式实现。因为并发时代的CPU在指令集上必然也需要相应的改变,并且前面也说过,这种并发C语言必须适应现在的硬件模型,保持C语言与硬件的简单对应关系。

另外一个方面如我在《语言的缺陷》中提到过的,我认为这个并发C语言要能够为程序员提供更多的优化可能性——即使付出的代价是可能因此丧失易用性。并发易用性的问题应该交给更高一级的语言去完成,理由与我不赞成给C增加GC差不多——每一种语言都有自己的定位,保持这一点比试图万能更重要。

具体一点说就要举例子了:

比 如Java和Delphi里都有一个Synchronize的东东,它的作用就是保证并发安全。但是它的实现方式就是简单地把加了这个东东的函数做成单线 程。所以这个东东虽然能够简单地“解决”并发问题,但实际上是一种不得已的退化(多并发退化为非并发)手段。虽然可能可以把这个东东的粒度从函数级降到语 句级,以便在应用中使这种退化程度尽可能少(非并发的部分尽可能少),但作用毕竟还是有限的。我认为并发C应该提供更加灵活的并发控制机制。

比 如有四个代码段:A, B, C, D,其中A和B不能并发,B和C不能并发,C和D不能并发,D和A不能并发,并且四段之间没有顺序依赖。如果用Sychronize的方式,则这四段实际 上只能以非并发方式执行,但我认为并发C在语言上应该能够让程序员允许AC并发和BD并发,这样效率就可以得到提高。

这就是我所说的,并发C要给程序员留下最大的优化可能性。

但是到更高一级的语言来说,易用性就显得很重要,最好是能对并发提供隐含支持。

就拿Python来说,在matplotlib里有一个asarray,可以把一个list当成一个数字进行运算——相当于数学上的一维矩阵(向量)的运算。对于这种运算,解释器完全可以隐含处理成并发的操作,而这个过程对于程序员来说是透明的。

在这一点上,我有一种感觉:未来在并发普及以后,动态语言的运行效率将会有很大的提高,其与原生语言的性能差别也许就像现在VM语言与原生语言的差别那么小。当然而VM语言也会更快一些,只是幅度有限——因为现在已经很快了。

事实上,并发语言并不是什么新鲜东西,毕竟SMP存在的时间也不短了,只是以前不属于民用罢了。而且据我所知,早在二十年前就有过并发的Pascal,只是不知道现在它还健 在否。

就拿最新的一种并发语言Fortress来说,这是一种专门用于并发应用而设计的,用于替代Fortran的新语言(多谢令狐指正)。在我看来,Fortran是很需要并发支持的(也许在如天气预报那样的高端应用中早已经有专用的并发Fortran), 因为它通常用于科学计算,而这种计算中常见的矩阵运算是最适用并发的情况之一。

令狐在看过Fortress的Spec后称:

我粗粗的看了一下他的Spec,关于并发,它主要有3块支持:Atomic Expression(类似于我们讨论的细粒度Sync),隐式并发(对于某些操作自动以并发形式操作)和显式并发(显式声明线程)。
我觉得“并发C语言”也应该具有这三种并发支持,1和3不用说了,上面你都已经讨论了,主要是2。我为什么认为隐式并发也是并发C的一个必要元素呢?我感 觉,对并发做一定程度的封装,有利于更方便的使用并发,也有利于培养用户的并发概念。(试想一下,如果C++不提供那个降低效率的虚函数机制,用户可能很 难搞清楚到底什么是多态)。这样的语言,才真正意义上是一个“支持并发的语言”。
当然,作为一种中级语言,这种隐式并发可以是非常有限的,比如,我能想到的:对于LONGLONG类型的操作,可以以隐式并发的形式完成;对数组的某些操作,可能也可以以隐式并发的形式完成。

这个我是同意的,只要在不破坏C的核心功能基础上,适当的隐式并发也是有必要的。