diff options
| author | Rob Pike <r@golang.org> | 2009-10-20 12:30:39 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2009-10-20 12:30:39 -0700 |
| commit | 0f60a452df747c97b012636454382f70cddcac31 (patch) | |
| tree | 17c43a4a92a0018db64265bde52fa59b994972d6 | |
| parent | a16808f7d83d2dce5fda23a49404c84cf15f5759 (diff) | |
| download | golang-0f60a452df747c97b012636454382f70cddcac31.tar.gz | |
start the concurrency discussion. work from the outside in because this is a toughie.
also fix a pedantry in the language design faq.
R=rsc
DELTA=113 (94 added, 16 deleted, 3 changed)
OCL=35922
CL=35928
| -rw-r--r-- | doc/effective_go.html | 114 | ||||
| -rw-r--r-- | doc/go_lang_faq.html | 2 |
2 files changed, 97 insertions, 19 deletions
diff --git a/doc/effective_go.html b/doc/effective_go.html index 0efd224a7..23eaf3ce7 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -1,7 +1,5 @@ <!-- Effective Go --> -<!-- testing?; concurrency; initialization--> - <h2 id="introduction">Introduction</h2> <p> @@ -194,7 +192,7 @@ If the package is simple, the package comment can be brief. <p> Comments do not need extra formatting such as banners of stars. The generated output may not even be presented in a fixed-width font, so don't depend -on spacing for alignment—<code>godoc</code>, like <code>gofmt</code>, +on spacing for alignment—<code>godoc</code>, like <code>gofmt</code>, takes care of that. Finally, the comments are uninterpreted plain text, so HTML and other annotations such as <code>_this_</code> will reproduce <i>verbatim</i> and should @@ -830,7 +828,7 @@ func NewFile(fd int, name string) *File { </pre> <p> -There's a lot of boilerplate in there. We can simplify it +There's a lot of boiler plate in there. We can simplify it using a <i>composite literal</i>, which is an expression that creates a new instance each time it is evaluated. @@ -1838,6 +1836,100 @@ is never used. </p> +<h2 id="concurrency">Concurrency</h2> + +<h3 id="sharing">Share by communicating</h3> + +<p> +Concurrent programming in many environments is made difficult by the +subtleties required to implement correct access to shared variables. Go encourages +a different approach in which shared values are passed around on channels +and, in fact, never actively shared by separate threads of execution. +Only one goroutine has access to the value at any given time. +Data races cannot occur, by design. +To encourage this way of thinking we have reduced it to a slogan: +</p> +<blockquote> +Do not communicate by sharing memory; +instead, share memory by communicating. +</blockquote> +<p> +This approach can be taken too far. Reference counts may be best done +by putting a mutex around an integer variable, for instance. But as a +high-level approach, using channels to control access makes it easier +to write clear, correct programs. +</p> +<p> +Another way to think about this model is to consider a typical single-threaded +program running on one CPU. It has no need for synchronization primitives. +Now run another such instance; it too needs no synchronization. Now let those +two communicate; if the communication is the synchronizer, there's still no need +for other synchronization. Consider Unix pipelines: they fit this model just +fine. Although Go's approach to concurrency originates in Hoare's +Communicating Sequential Processes (CSP), +it can also be seen as a type-safe generalization of Unix pipes. +</p> + +<h3 id="goroutines">Goroutines</h3> + +<h3 id="channels">Channels</h3> + +<h3 id="leaky_buffer">A leaky buffer</h3> + +<p> +The tools of concurrent programming can often make non-concurrent +ideas easier to express. Here's an example abstracted from an RPC +package. The client goroutine loops receiving data from some source, +perhaps a network. To avoid allocating and freeing buffers, it keeps +a free list, and uses a buffered channel to represent it. If the +channel is empty, a new buffer gets allocated. +Once the message buffer is ready, it's sent to the server on +<code>serverChan</code>. +</p> +<pre> +var freelist = make(chan *Buffer, 100) +var server_chan = make(chan *Buffer) + +func client() { + for { + b, ok := <-freeList; // grab one if available + if !ok { // free list empty; allocate a new buffer + b = new(Buffer) + } + load(b); // grab the next message, perhaps from the net + serverChan <- b; // send to server + } +} +</pre> +<p> +The server loop receives messages from the client, processes them, +and returns the buffer to the free list. +</p> +<pre> +func server() { + for { + b := <-serverChan; // wait for work + process(b); + _ = freeList <- b; // reuse buffer if room + } +} +</pre> +<p> +The client's non-blocking receive from <code>freeList</code> obtains a +buffer if one is available; otherwise the client allocates +a fresh one. +The server's non-blocking send on freeList puts <code>b</code> back +on the free list unless the list is full, in which case the +buffer is dropped on the floor to be reclaimed by +the garbage collector. +(The assignment of the send operation to the blank identifier +makes it non-blocking but ignores whether +the operation succeeded.) +This implementation builds a leaky bucket free list +in just a few lines, relying on the buffered channel and +the garbage collector for bookkeeping. +</p> + <h2 id="errors">Errors</h2> <p> @@ -1933,20 +2025,6 @@ template eventually datafmt </p> -<h2>Concurrency</h2> - -<h3 id="share-memory">Share memory by communicating</h3> - -<p> -Do not communicate by sharing memory; -instead, share memory by communicating. -</p> - -<p> -XXX, more here. -</p> - - <h2>Testing</h2> <h3 id="no-abort">Run tests to completion</h3> diff --git a/doc/go_lang_faq.html b/doc/go_lang_faq.html index 21466437f..a6d1d670b 100644 --- a/doc/go_lang_faq.html +++ b/doc/go_lang_faq.html @@ -167,7 +167,7 @@ issues around order of evaluation of <code>++</code> and <code>--</code> are eliminated as well. The simplification is significant. As for postfix vs. prefix, either would work fine but the postfix version is more traditional; insistence on prefix arose -with the STL, part of a language whose name contains, ironically, a +with the STL, a library for a language whose name contains, ironically, a postfix increment. </p> |
