Clojure / Java中的Goroutines的等效实现

huangapple go评论78阅读模式
英文:

Equivalent of Goroutines in Clojure / Java

问题

我最近喜欢看Google IO关于Go并发模式的讲座

虽然Go的并发方式(协程,通过通道进行通信)与Clojure(不可变性,管理引用,STM)明显不同,但在某些情况下,Go的并发方式似乎在Clojure环境中仍然有用。

那么,在Clojure或Java中是否有直接等效于Go并发原语(可能是一个库)的东西,特别是:

  • 类似channel的对象,它们在两端都有可用的读取器和写入器之前会阻塞
  • 类似select的结构,可以等待多个通道上的结果

P.S. 如果有Java的解决方案,我也非常满意,因为从Clojure中使用它很容易。

更新 自从最初提出这个问题以来,Clojure现在有了core.async,它提供了所有这些功能以及更多。

英文:

I recently enjoyed watching the Google IO talk on Go Concurrency patterns

Although the Go approach to concurrency (groutines, communication over channels) is clearly different to Clojure (immutability, manged references, STM), it seemed like the Go approach could still be useful in some circumstances in a Clojure context.

So is there a direct equivalent in Clojure or Java for Go's concurrency primitives (perhaps a library), in particular:

  • channel-like objects that block until a reader and writer are available at both ends
  • A select-like construct that can wait for results on multiple channels

P.S. Perfectly happy with a Java solution since it would be easy to use from Clojure

UPDATE Since the question was originally asked, Clojure now has core.async which provides all this functionality and more.

答案1

得分: 6

你应该查看core.async。这是由Rich Hickey编写的一个实现go风格通道的库。

英文:

You should check out core.async. It is a library written by Rich Hickey that implements go style channels.

答案2

得分: 3

这有点令人困惑。你是指“在写入时,阻塞直到读取器可用;在读取时,阻塞直到写入器可用”吗?我是代表线程而不是构造体说话,构造体不能阻塞,只有线程可以阻塞。(为了避免混淆,构造体会指示线程阻塞)。

如果我的假设是正确的,那么在标准Java中有两个选项。

  1. SynchronousQueue
  2. TransferQueue(尽管这也可以用作缓冲通道)

一个类似于select的构造体,可以等待多个通道上的结果

据我所知,没有真正的select类似的构造体。你能得到的最接近的是ExecutorCompletionService,它会在下一个可用的任务完成时返回。

英文:

> channel-like objects that block until a reader and writer are
> available at both ends

This is a bit confusing. Do you mean "blocks until, if writing, a reader is available or, if reading, a writer is available"? I am speaking on behalf of the threads and not the construct, a construct cannot block only threads can. (To avoid confusion a construct would instruct threads to block).

If my assumption is true there are two options you can have (in standard Java).

  1. SynchronousQueue
  2. TransferQueue (though this can be used as a buffer channel also)

> A select-like construct that can wait for results on multiple channels

As far as I know there arent any true select like constructs. The closest you can have is a ExecutorCompletionService that will return when the next available task submitted is completed.

答案3

得分: 3

我最近写了一个Clojure库go-lightly,用于支持使用Go并发结构进行编程,将一些Clojure习惯用法应用到并发编程风格中。

Go并发编程的核心结构包括:

  1. Go协程
  2. 同步(阻塞)通道
  3. 有界的、大多是异步(非阻塞)通道
  4. select操作符,从多个通道中读取下一个可用的消息
  5. 通道读取/写入/选择的超时操作

go-lightly库具备所有这些功能,并构建在Java和Clojure可用的功能之上。真正的Go协程是多路复用到线程上的,而不是完全使用一个线程的整个生命周期。在go-lightly中,我使用Clojure的future宏来构建go协程,所以这是Go模型在JVM上最薄弱的部分。

我尝试过使用lamina,但它缺乏有界通道(在某些场景下可能需要)和我所知道的方式中没有一种方法可以在将消息放入通道时使生产者阻塞。这是Go并发模型的一个关键特性。

我在git仓库中包含了一些使用go-lightly库的示例。大多数示例都基于Rob Pike在过去两年中的演讲中给出的示例。

构建一个基于JCSP的Clojure库将是有趣的,但我还没有进行过研究。

英文:

I have recently written go-lightly, a Clojure library to support programming with Go concurrency constructs, putting some Clojure idioms on that concurrent programming style.

The core constructs of Go concurrency programming are:

  1. Go routines
  2. Synchronous (blocking) channels
  3. Bounded, mostly asynchronous (non-blocking) channels
  4. A select operator that reads the next available message from multiple channels
  5. Timeout operations on channel read/writes/selects

The go-lightly library has all of these features, building on top of features available in Java and Clojure. True Go routines are multiplexed onto threads, rather than fully using a thread for its full lifetime. In go-lightly, I build go routines on top of the Clojure future macro, so this is the weakest part of the Go model on the JVM.

I tried using lamina, but it lacks bounded channels (which you might want in some scenarios and is a part of the Go buffered channel model) and as far as I can tell lacks a way to have a producer block when putting a message onto a channel. That is a crucial feature of the Go concurrency model.

I've included a number of examples using the go-lightly library in the git repo. Most are based on examples that Rob Pike has given in talks over the past two years.

It would be interesting to build a Clojure library on top of JCSP, but I haven't researched that yet.

答案4

得分: 2

不了解Go的情况下,可以看一下Lamina,看看它是否符合你的需求。https://github.com/ztellman/lamina

英文:

Without knowing anything about Go, have a look at Lamina to see if it fits what you are looking for https://github.com/ztellman/lamina

答案5

得分: 1

你可能想看一下Quasar/Pulsar。它非常新,但正是你所需要的。

英文:

You might want to look at Quasar/Pulsar. It's very new, but it's exactly what you're looking for.

答案6

得分: 0

看一下Joxa。它是一种类似Clojure的Lisp方言,目标是Erlang虚拟机。<p>
Erlang以轻量级的小于1000字节的进程而闻名。<p>
另外Erjang也与此相关,可能会对你有兴趣。它是在JVM上实现的Erlang虚拟机。<p>
所以理论上你可以将Joxa编译成BEAM,然后在JVM上运行它。不过我不建议这样做 :-).

英文:

Take a look at Joxa. It is a Clojure-like dialect of Lisp targeting Erlang Virtual Machine. <p>
And Erlang is known for light-weight sub-1000-bytes processes. <p>
Also Erjang is somewhat related and could be of interest to you. It's an implementation of Erlang Virtual Machine on top of JVM.<p>
So theoretically you can compile Joxa to BEAM and then still run it on JVM. Not that I would recommend it :-).

答案7

得分: 0

the akka actor ~= goroutine+channel

英文:

the akka actor ~= goroutine+channel

答案8

得分: 0

我强烈推荐JCSP,它基于Occam/transputer算法。该API实现的关键部分已经使用形式化方法和形式证明算法进行了正确性检查,因此几乎是可靠的(在这方面,Alternative类是主要的成就)。

JCSP非常好...然而,JVM所施加的限制仍然存在,尤其是线程的高成本。在Go或Occam中,线程可以达到数百万个,但在JVM上不行。

英文:

I highly recommend JCSP, based on the Occam/transputer algorithms. Key parts of this API implementation have been checked for correctness using formal methods and formal prover algorithms, so are about as reliable as is possible (the Alternative class is the prime achievement in this regard).

JCSP is very good ... however the downside remains the limitations imposed by the JVM, especially the high cost of threads. In Go or Occam, threads can number in millions, but not so on the JVM.

huangapple
  • 本文由 发表于 2012年7月3日 02:14:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/11298961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定