为什么函数式语言被认为是多线程环境的福音?

时间:2010-05-25 23:42:11

标签: multithreading functional-programming

我听到很多关于函数式语言的知识,以及它们如何很好地扩展,因为函数周围没有状态;因此,该功能可以大规模并行化。

然而,这对我来说没什么意义,因为几乎所有真实世界的实用程序都需要/有状态来照顾。我还发现有趣的是,大多数主要的扩展库,即MapReduce,通常都是用C或C ++等命令式语言编写的。

我想听听功能训练营的消息,我听到这种炒作来自......

5 个答案:

答案 0 :(得分:13)

添加一个词很重要:“没有共享状态”。

任何有意义的程序(使用任何语言)都会改变世界的状态。但是(某些)功能语言使得无法同时从多个线程访问相同的资源。缺少共享状态会使多线程安全。

答案 1 :(得分:7)

Haskell,Scheme等功能语言具有所谓的“纯函数”。纯函数是一种没有副作用的函数。它不会修改程序中的任何其他状态。这是线程安全的定义。

当然,您可以用命令式语言编写纯函数。您还可以找到Python,Ruby甚至C#等多范式语言,您可以在其中执行命令式编程,函数式编程或两者兼而有之。

但Haskell(等)的观点是你不能写一个非纯函数。嗯,这不是严格正确的,但大多数情况下都是如此。

类似地,许多命令式语言具有不可变对象的原因大致相同。不可变对象是一旦创建状态就不会改变的对象。根据定义,不可变对象也是线程安全的。

答案 2 :(得分:6)

你在谈论两件不同的事情而没有意识到。

是的,大多数真实世界的程序都有某个地方,但是如果你想进行多线程处理,那个状态不应该无处不在,事实上,地方越少它在,越好。在功能程序中,默认情况下不具有状态,您可以准确地将状态引入您需要的位置,而不是其他地方。处理状态的那些部分不会像多线程那样容易,但由于程序的所有其余部分都没有副作用,因此执行这些部分的顺序无关紧要,这消除了并行化的巨大障碍

答案 3 :(得分:4)

  

然而,这对我来说没什么意义,因为几乎所有的现实世界   实际课程需要/有状态照顾。

你会感到惊讶!是的,所有程序都需要一些状态(特别是I / O),但通常你不需要更多。仅仅因为大多数程序都有大量的状态并不意味着他们需要它。

使用函数式语言进行编程可以鼓励您使用较少的状态,从而使您的程序更容易并行化。

许多函数式语言都是“不纯的”,这意味着它们允许某些状态。 Haskell没有,但是Haskell有monad,它基本上可以让你从零开始获得一些东西:你使用无状态结构获得状态。 Monads使用起来有点繁琐,这就是为什么Haskell强烈鼓励你将状态限制在尽可能小的程序中。

  

我也发现大多数主要的扩展库都很有趣,即   MapReduce通常用命令式语言编写,如C或C ++。

在C / C ++中编程并发应用程序是“难”的。这就是为什么最好在库中进行经过严格测试和检查的所有危险物品。但是你仍然可以获得C / C ++的灵活性和性能。

答案 4 :(得分:2)

高阶函数。考虑一个简单的简化操作,对数组的元素求和。在命令式语言中,程序员通常会自己编写一个循环并一次执行一个元素的减少。

但是这个代码制作多线程并不容易。当你编写一个循环时,你假设一个操作顺序,你必须说明如何从一个元素到另一个元素。你真的只想说“对数组求和”并使用编译器,运行时或其他任何东西,决定如何处理数组,在多个内核之间根据需要划分任务,并将这些结果组合在一起。因此,不是编写一个循环,而是在其中嵌入一些附加代码,另一种方法是将表示“添加”的内容传递给可以执行divvying的函数。一旦你这样做,你就会在功能上写作。你将一个函数(加法)传递给另一个函数(reducer)。如果以这种方式编写,那么它不仅会使代码更具可读性,而且当您更改体系结构或想要为异构体系结构编写时,您不必更改夏天,只需更改reducer。在实践中,您可能有许多不同的算法,它们共享一个减速器,因此这是一个很大的收益。

这只是一个简单的例子。您可能希望以此为基础。在2D数组上应用其他函数的函数,将函数应用于树结构的函数,组合函数以应用函数的函数(例如,如果您具有上面的树和下面的数组的层次结构),等等。