是否难以实施Go';Scala中的并发模式?

是否难以实施Go';Scala中的并发模式?,scala,concurrency,go,Scala,Concurrency,Go,毫无疑问,Go的语法比Scala的简单得多。它还具有较少的语言特性。我非常喜欢使用Go编写并发代码的简单性 事实证明,performant代码是非阻塞代码(请参阅),Go和Scala在这方面都非常出色 我的问题是如何通过实现相同的并发模式,在Scala中编写与Go程序行为完全相同的程序。首先想到的是以类似的方式在渠道中使用期货 我在找 Go并发模式在Scala中的可能实现 如果Go构造很难在Scala中精确模拟 代码片段 非常感谢您的帮助 [编辑]Go并发模式的几个示例 扇入 func f

毫无疑问,Go的语法比Scala的简单得多。它还具有较少的语言特性。我非常喜欢使用Go编写并发代码的简单性

事实证明,performant代码是非阻塞代码(请参阅),Go和Scala在这方面都非常出色

我的问题是如何通过实现相同的并发模式,在Scala中编写与Go程序行为完全相同的程序。首先想到的是以类似的方式在渠道中使用期货

我在找

  • Go并发模式在Scala中的可能实现
  • 如果Go构造很难在Scala中精确模拟
  • 代码片段
非常感谢您的帮助

[编辑]Go并发模式的几个示例

扇入

func fanIn(input1, input2 <-chan string) <-chan string {
  c := make(chan string)
  go func() {
    for {
      select {
        case s := <-input1:  c <- s
        case s := <-input2:  c <- s
      }
    }
  }()
  return c
}

func fanIn(input1,input2Go)在核心语言中内置了并发特性,而Scala使用Java的
Java.util.concurrent
中的和并发原语

在Scala中,习惯使用基于线程的并发或,而Go并发是基于线程的

虽然这两种语言之间的并发原语不同,但看起来有一些相似之处

In-Go并发通常通过和实现。还有其他更传统的方法

据我所知,在Scala中,任何声明为“Runnable”的类都将在单独的线程中启动,并且不会阻塞。这在功能上类似于goroutines

在Scala中,队列可用于以与Go中的通道类似的方式在例程之间传递信息

编辑:正如所指出的,“Scala的队列和Go通道之间的关键区别在于,默认情况下,Go的通道在写入时阻塞,直到有东西准备从它们读取,在读取时阻塞,直到有东西准备写入它们。”。这需要写入通道的任何Scala实现中


编辑2:正如所指出的,“您可以使用Async-github.com/Scala/Async在Scala中执行并发操作,而不使用可见回调,但如果没有回调,您根本无法执行并发操作,因为JVM当前的实现方式是不可能的。”

感谢大家提出的建设性意见

有关更多信息,请参阅:


    • 简单的回答是不,这并不难

      正如您所知,通过消息传递实现的并发可以使用阻塞或非阻塞同步原语进行操作。Go的通道可以同时执行这两种操作—它们可以是无缓冲的,也可以是缓冲的—由您选择

      JVM语言中有很多关于非阻塞并发总是优越的说法。一般来说,这不是真的;这只是JVM的一个特性,即线程在其上非常昂贵。作为回应,大多数JVM并发API只提供非阻塞模型,尽管这是不幸的

      对于最多1000个JVM线程的相对适度的并发性,即使在JVM上,阻塞并发也可以非常有效地工作。因为这种风格不涉及任何回调,所以很容易编写,稍后再读取

      坎特伯雷大学的优秀图书馆是使用java编写Java/Scala/…程序的好方法。这是GO使用的相同样式;JCSP通道与GO信道非常相似,提供了无缓冲或缓冲(或覆盖固定缓冲区)的选项。大小。它的

      select
      称为
      Alternative
      ,JCSP开发人员通过正式分析证明它是正确的

      但是,由于JVM实际上无法支持1000多个线程,这对于某些应用程序领域来说是不合适的



      脚注:在Maven repos中,JCSP的当前版本是v1.1rc5,与JCSP网站上所说的相反。

      显然有一个第三方库(Netflix),它提供对Scala的反应式扩展(还包括Java和其他JVM语言)。 RX的观测值可以类似于Go的通道


      文档也很有用,它提供了常见模式的可视化表示。

      良好的实现是非常重要的

      也就是说,您可以以“阻塞”的方式实现一个,其中每个go阻塞原语(通道等待)实际上都会阻塞执行线程。实现虽然很简单,但毫无用处

      另一种选择是构建一种机制,它允许异步地“暂停/恢复”等待的执行流。因为我们在JVM中没有内置的对延续的支持,所以实现这一点非常复杂,需要或AST转换或字节码编织

      对于#1方法的实现(即在SIP-22异步之上使用AST转换),您可以查看(警告:我是作者)


      更新:scala3的scala-gopher-2.0.0基于dotty cps async,它在异步块内进行一元cps转换。

      在JVM上实现CSP风格的并发并不容易,无论是Java还是scala。原因是CSP基于具有简化上下文的线程,通常称为绿色线程。简化的文本占用更少的内存,这意味着可以运行比OS线程或Java线程多得多的绿色线程(1个Java线程对应1个OS线程)。我曾经尝试过:使用4 GB RAM,可以启动大约80.000个Goroutine(Go中绿色线程的变体),而不是大约2.000个Java线程

      这有什么关系呢?CSP的想法是,如果某个通道不包含数据,那么“只有”一个绿色线程丢失,它现在位于该通道上,直到接收到输入为止。假设您有一个web应用程序正在被40000个用户访问。可以在具有4 GB RAM的机器上启动的80000个Goroutines可以立即处理这些40000个连接(1个入站连接和1个出站连接).如果没有绿色线程,则需要