gpt4 book ai didi

multithreading - 纯函数式编程中的竞争条件

转载 作者:行者123 更新时间:2023-12-04 06:41:28 24 4
gpt4 key购买 nike

我遇到过这样的说法:

“以函数式风格编程使呈现给您的代码的状态变得明确,这使得推理变得更加容易,并且在完全纯粹的系统中,使线程竞争条件成为不可能。”

我看到了这个观点,但我如何才能在现实世界的问题中实现这一点?

例如:

有一个具有两个功能的函数式程序:

def getMoney(actMoney: Integer, moneyToGet: Integer): Integer 
= actMoney - moneyToGet

def putMoney(actMoney: Integer, moneyToPut: Integer): Integer
= actMoney + moneyToPut

然后,我真的很想为给定的帐户定义函数 getActualMoney 和 saveActualMoney,但我不能,它们不是纯函数。那是因为我从某个内存中获取给定帐户的 Money 并将给定帐户的 Money 保存到某个内存中(有状态)。
def getActualMoney(accountNo: String): Integer = {...}

def saveActualMoney(accountNo: String, actMoney: Integer): Unit = {...}

所以我必须从“外部”获取我当前的资金。让我们说,我的程序正在以这种方式工作。现在我有两个同时的请求,第一个:拿一些钱,第二个给同一个账户放一些钱。当然我会得到两种不同的结果。所以存在竞争条件。

我明白,我应该在这个帐户“外部”编程代码上进行交易。所以,这种情况不应该发生。为了更好的并发,函数应该是这样的:
def getMoney(
acountNo: String,
actMoney: Integer,
moneyToGet: Integer): (String, Integer)
= (acountNo, actMoney - moneyToGet)

def putMoney(
acountNo: String,
actMoney: Integer,
moneyToPut: Integer): (String, Integer)
= (acountNo, actMoney + moneyToPut)

这是怎么回事?值得做吗?

最佳答案

虽然引用在技术上是正确的,因为你不能在纯函数式代码中使用竞争条件,你确实需要有副作用才能让程序做任何有用的事情而不是计算一个值,所以它有点虚伪,虽然同时,它确实说明了一个有用的区别。

以最小化副作用和最大化纯函数式代码的风格进行编程将减少在那些你知道你明确使用副作用的地方可能发生竞争条件的代码区域,而这通常是纯函数式编程吹捧的好处倡导者。

对于您的示例:如果有资金的帐户只是仅存在于您的程序中的模拟,那么通过让帐户上的每个操作返回一个具有更新值的新帐户对象,将它们保留为纯函数会很容易。如果你这样做,一般来说你会得到纯函数式代码的好处:能够通过使用“等式推理”来推理引用透明的代码,在这里你可以假设对函数的任何调用都等同于值函数返回给定它传递的参数,不管你以什么顺序调用它多少次。 (这是为了回答你的“值得做吗?”的问题)

但是,如果您谈论的是将帐户和余额存储在外部数据库中的系统,那么您肯定需要副作用,并且您将不得不像您一样关注操作顺序和潜在的竞争条件任何其他语言。但是,通过隔离您的副作用,您可以更加确定您必须在哪里关注此类并发问题,并且还可以使用更高级别的并发抽象,例如 MVars、IORefs 或 STM(在 Haskell 和,似乎是 Scala),它鼓励对不纯数据使用纯操作——保持事物隔离和可组合。

关于multithreading - 纯函数式编程中的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30079695/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com