当我学习Java时,使用了基础,Pascal,COBOL和C的大约20年的过程编程背景。当时,我认为关于Java的最困难的事情是将我的头放在OOP术语和概念上。如今,有了将近8年的坚实Java经验,我得出的结论是,用Java和类似C#这样的类似语言进行编程的最困难的事情就是多线程/并行方面。

编码可靠且可扩展的多线程应用程序真是太难了!随着处理器的发展趋势是“更广泛”而不是更快地发展,它正迅速变得至关重要。

当然,最困难的区域是控制线程之间的交互以及由此产生的错误:死锁,竞争条件,陈旧数据和延迟。

因此,我对您的问题是:您采用哪种方法或方法来生成安全的并发代码,同时减少出现死锁,延迟和其他问题的可能性?我想出了一种非常规的方法,但是在一些大型应用程序中效果很好,我将在此问题的详细解答中分享它。

最佳答案

目前,有很多技术正在进入公众意识(例如:最近几年)。一个很大的是演员。这是Erlang最初带到网格中的东西,但后来被诸如Scala(JVM上的actor)之类的新语言所继承。尽管参与者确实不能解决所有问题,但确实可以使推理代码和确定故障点变得容易得多。由于它们迫使您使用通过共享可变状态传递的连续性,因此它们也使并行算法的设计变得更加简单。

您应该关注Fork / Join,尤其是在使用JVM的情况下。道格·李(Doug Lea)撰写了有关该主题的开创性论文,但是多年来,许多研究人员对此进行了讨论。据我了解,Doug Lea的参考框架计划包含在Java 7中。

在侵入性较小的水平上,简化多线程应用程序通常所需的唯一步骤仅仅是降低锁定的复杂性。细粒度的锁定(Java 5风格)对于吞吐量非常有用,但是很难正确实现。通过Clojure获得一定关注的另一种锁定方法是软件事务存储(STM)。这与常规锁定基本上是相反的,因为它是乐观的而不是悲观的。首先假设您不会发生任何冲突,然后让框架在问题发生时和问题解决时予以解决。数据库通常以这种方式工作。这对于低冲突率的系统上的吞吐量非常有用,但是最大的胜利在于算法的逻辑组件化。无需将某个锁(或一系列锁)与某些数据任意关联,您只需将危险代码包装在事务中,然后让框架找出其余的代码即可。您甚至可以从像GHC的STM monad或我的实验性Scala STM之类的STM实现中获得相当多的编译时检查。

有许多用于构建并发应用程序的新选项,您选择哪种取决于您的专业知识,语言和您要建模的问题类型。通常,我认为参与者与持久的,不变的数据结构相结合是一个可靠的选择,但是正如我所说的,STM的侵入性较小,有时可以带来更直接的改进。

07-27 19:51