Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何避免可变状态(多线程时)_Multithreading_Language Agnostic_Concurrency - Fatal编程技术网

Multithreading 如何避免可变状态(多线程时)

Multithreading 如何避免可变状态(多线程时),multithreading,language-agnostic,concurrency,Multithreading,Language Agnostic,Concurrency,多线程是很难的。你唯一能做的就是非常仔细地编程并遵循好的建议。我从这个论坛的答案中得到的一个很好的建议是避免可变状态。我知道这在Erlang语言中是强制执行的。但是,我不知道如何在没有严重性能损失和大量缓存的情况下实现这一点 比如说。你有一个很大的对象列表,每个对象包含相当多的属性;换句话说:一个大的数据结构。假设您有一堆线程,它们都需要访问和修改列表。如果没有共享内存,又不必在每个线程中缓存整个数据结构,如何做到这一点 更新:在阅读了到目前为止的反应之后,我想更加强调性能。你不认为复制相同的数

多线程是很难的。你唯一能做的就是非常仔细地编程并遵循好的建议。我从这个论坛的答案中得到的一个很好的建议是避免可变状态。我知道这在Erlang语言中是强制执行的。但是,我不知道如何在没有严重性能损失和大量缓存的情况下实现这一点

比如说。你有一个很大的对象列表,每个对象包含相当多的属性;换句话说:一个大的数据结构。假设您有一堆线程,它们都需要访问和修改列表。如果没有共享内存,又不必在每个线程中缓存整个数据结构,如何做到这一点


更新:在阅读了到目前为止的反应之后,我想更加强调性能。你不认为复制相同的数据会使程序比共享内存慢吗

我想第一个问题是:他们为什么需要修改列表?他们是否可以将更改作为修改列表返回,而不是实际修改共享列表?他们能处理一个看起来像是原始列表的可变版本,但实际上只是局部可变的列表吗?您是在更改列表中的哪些元素,还是仅更改这些元素的属性


这些只是问题而不是答案,但我试图鼓励你们用不同的方式思考你们的问题。把大局看成是你想要完成的任务,而不是以一种正常的、强制性的、易变的方式去思考解决问题的方法。改变思考问题的方式是非常困难的,但你可能会发现你会得到一些很棒的“啊哈!”时刻:)

处理多线程和大数据集时会有很多陷阱。避免可变状态的建议是为了尽量让您的生活更轻松,如果您能够遵循该指南(即,如果您没有可变状态,那么多线程将更容易)

如果您有大量的数据需要修改,那么您可能无法避免可变状态。另一种方法是将数据划分成块,每个块都传递给线程进行操作。可以处理该块,然后将其传回,然后控制器可以在必要时执行更新。在这个场景中,您已经从线程外删除了可变状态


如果不能做到这一点,并且每个线程都需要对完整列表进行更新访问(即,它可以随时更新列表中的任何项目),那么您将在尝试确保您的锁定策略和并发性问题得到解决时获得很多乐趣。我确信有些场景需要这样做,避免可变状态的设计模式可能不适用。

不是每个算法都可以成功地并行化

如果您的程序没有任何“并行结构”,那么您注定要使用锁定和共享的可变结构

如果您的算法表现出结构,那么您可以用一些模式或形式(例如,宏数据流图)来表示您的计算,这使得选择不可变的数据结构变得很简单


所以:考虑算法的结构,而不是要使用的数据结构的属性。

仅仅使用不可变的数据对象是一个很大的帮助。
修改列表听起来像是一个构造的参数,但是考虑不知道列表的颗粒状方法。

如果你真的需要更新结构,一种方法是用一个单独的工作者线程来拾取由互斥体所标识的固定区域的更新请求。 如果你聪明,你可以在不影响任何“阅读”的情况下更新结构 线程(例如,如果要添加到数组的末尾,则需要进行所有工作来添加新结构,但只有在最后一条指令增加NoOfMembers计数时,读取线程才会看到新条目,直到您执行此操作,或者将数据排列为对结构的引用数组,当您要更新所需的结构时)py当前成员,更新它,然后作为最后一个操作替换数组中的引用)


其他线程只需要检查一个简单的“在进程中更新”只有当不可变集合需要更新时才使用互斥。通过阅读Eric Lippert的文章,你可以很好地开始思考不可变集合,它们在哪里适用,它们如何在不需要大量复制的情况下实际工作,等等


你是对的,我的例子有点模糊。我会考虑一下,然后试着想出一个更好的例子。这是一个很好的答案。非常感谢。一个构建的论点?:-)当然不是。它经常出现在我有大量密切相关数据的情况下。事实上,您可能会将其分成若干部分,但我希望这会使程序代码变得更长、更复杂。不要假设您的程序应该是多线程的:如果您想使其分布式的话?Datastruct复制在这里是一个巨大的胜利。你是对的。在我们的应用程序中,用户界面被分离为通过TCP连接的瘦客户机。我们将相当一部分数据缓存在UI端。结果是产生了更多的代码和更复杂的程序。或者从他移植代码的书中-