<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Chapter 10 Channels and select on Go: Under the Hood</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/</link><description>Recent content in Chapter 10 Channels and select on Go: Under the Hood</description><generator>Hugo</generator><language>en</language><atom:link href="https://golang.design/under-the-hood/en/part3concurrency/ch10chan/index.xml" rel="self" type="application/rss+xml"/><item><title>10.1 Channels and the Engineering of CSP</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/model/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/model/</guid><description>&lt;h1 id="101-channels-and-the-engineering-of-csp"&gt;10.1 Channels and the Engineering of CSP&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;A recorded talk accompanies this section: &lt;a href="https://www.youtube.com/watch?v=d7fFCGGn0Wc"&gt;online on YouTube&lt;/a&gt;,
&lt;a href="https://changkun.de/s/chansrc/"&gt;Google Slides deck&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CSP gives Go a claim: processes do not share state, they coordinate solely by passing messages
(&lt;a href="https://golang.design/under-the-hood/en/part1overview/ch01intro/csp/"&gt;1.3&lt;/a&gt;). This section is concerned with a different question:
for an engineering language to make this claim real, what shape must &amp;ldquo;communication&amp;rdquo; take so that
an ordinary programmer can reach for it and get it right. Go&amp;rsquo;s answer is the channel, a first-class
primitive that is at once synchronization and communication. We begin by laying out its model at the
surface of the language, its type, its send and receive syntax, the two semantics of buffered versus
unbuffered, directional restriction, and nil behavior, building the intuition that the later sections
will need as they descend into the runtime implementation (&lt;a href=".././impl"&gt;10.2&lt;/a&gt;–&lt;a href=".././pattern"&gt;10.7&lt;/a&gt;).&lt;/p&gt;</description></item><item><title>10.2 hchan: The Internal Structure of a Channel</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/impl/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/impl/</guid><description>&lt;h1 id="102-hchan-the-internal-structure-of-a-channel"&gt;10.2 hchan: The Internal Structure of a Channel&lt;/h1&gt;
&lt;p&gt;&lt;a href=".././readme"&gt;10.1&lt;/a&gt; placed channels within the language from the angle of CSP: a channel is an explicit message conduit that fuses &amp;ldquo;communication&amp;rdquo; and &amp;ldquo;synchronization&amp;rdquo; into one. This section takes it apart. At runtime a channel is a struct called &lt;code&gt;hchan&lt;/code&gt;, and its whole secret amounts to a single lock, a ring of buffered storage, plus two wait queues. The structure is small, yet every field exists for a specific design reason. Once you understand these few pieces, the entire logic of sending, receiving, and select that follows (&lt;a href=".././sendrecv"&gt;10.3&lt;/a&gt;–&lt;a href=".././lockfree"&gt;10.6 The Memory Model and the Move Toward Lock-Free&lt;/a&gt;) is just &amp;ldquo;moving data, parking and waking goroutines on top of this one picture.&amp;rdquo;&lt;/p&gt;</description></item><item><title>10.3 Send, Receive, and Direct Handoff</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/sendrecv/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/sendrecv/</guid><description>&lt;h1 id="103-send-receive-and-direct-handoff"&gt;10.3 Send, Receive, and Direct Handoff&lt;/h1&gt;
&lt;p&gt;&lt;a href=".././impl"&gt;10.2&lt;/a&gt; laid out the skeleton of &lt;code&gt;hchan&lt;/code&gt;: a lock, a ring buffer &lt;code&gt;buf&lt;/code&gt;, plus a sender
queue &lt;code&gt;sendq&lt;/code&gt; and a receiver queue &lt;code&gt;recvq&lt;/code&gt;. This section brings the skeleton to life and answers
what actually happens inside the runtime during a single &lt;code&gt;ch &amp;lt;- v&lt;/code&gt; and a single &lt;code&gt;v := &amp;lt;-ch&lt;/code&gt;. Once
you understand this send/receive path, the two most frequently asked properties of a channel, why
an unbuffered channel is a single rendezvous, and why for it a receive happens before the
corresponding send completes (&lt;a href="../../ch11sync/mem"&gt;11.9&lt;/a&gt;), both come down to the same mechanism:
&lt;strong&gt;direct send / receive&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>10.4 The Semantics of Closing</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/close/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/close/</guid><description>&lt;h1 id="104-the-semantics-of-closing"&gt;10.4 The Semantics of Closing&lt;/h1&gt;
&lt;p&gt;In the previous sections, both sending and receiving were &amp;ldquo;one-to-one&amp;rdquo; rendezvous: one send pairs with one receive, and the surplus side blocks and waits. Closing is the only &amp;ldquo;one-to-many&amp;rdquo; operation on a channel. &lt;code&gt;close(ch)&lt;/code&gt; is issued by a single Goroutine, yet in an instant it wakes every receiver currently blocked on the channel and makes every blocked sender panic on the spot. This ability to &amp;ldquo;broadcast once and wake everyone&amp;rdquo; turns closing from a seemingly minor cleanup action into the most commonly used cancellation and wind-down mechanism in Go concurrency. The done channel pattern and &lt;code&gt;context&lt;/code&gt; cancellation (&lt;a href="https://golang.design/under-the-hood/en/part3concurrency/ch11sync/context/"&gt;11.8&lt;/a&gt;) both trace their roots back here.&lt;/p&gt;</description></item><item><title>10.5 The Implementation of select</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/select/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/select/</guid><description>&lt;h1 id="105-the-implementation-of-select"&gt;10.5 The Implementation of select&lt;/h1&gt;
&lt;p&gt;The previous sections covered send and receive on a single channel (&lt;a href=".././sendrecv"&gt;10.3&lt;/a&gt;) in
full. In practice, though, a Goroutine rarely watches just one channel: it wants to react to
&lt;strong&gt;whichever operation becomes ready first&lt;/strong&gt; among several sends and receives, and it also wants
to avoid blocking when &lt;strong&gt;none of them is ready&lt;/strong&gt;. &lt;code&gt;select&lt;/code&gt; exists exactly for this. Its semantics
look simple, yet the implementation has to solve two thorny problems at once: how to choose
&lt;strong&gt;fairly&lt;/strong&gt; when several branches are ready, and how to &lt;strong&gt;avoid deadlock&lt;/strong&gt; when locking several
channels to run a single select. These two concerns shape the entire structure of &lt;code&gt;selectgo&lt;/code&gt;,
and this section is built around them.&lt;/p&gt;</description></item><item><title>10.6 The Memory Model and the Lock-Free Evolution</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/lockfree/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/lockfree/</guid><description>&lt;h1 id="106-the-memory-model-and-the-lock-free-evolution"&gt;10.6 The Memory Model and the Lock-Free Evolution&lt;/h1&gt;
&lt;p&gt;The previous sections took the channel apart down to its parts: the direct handoff in &lt;a href=".././sendrecv"&gt;10.3&lt;/a&gt;
lets the sending and receiving ends pass a value directly, bypassing the ring buffer, and &lt;code&gt;select&lt;/code&gt; in
&lt;a href=".././select"&gt;10.5&lt;/a&gt; makes a random choice among several ready branches. These mechanisms explain how a
channel &amp;ldquo;runs&amp;rdquo;. This section answers two higher-level questions: what &lt;strong&gt;visibility guarantee&lt;/strong&gt; a channel
offers to a concurrent program, and an engineering mystery that is often raised, why a channel is still
&amp;ldquo;a lock plus a queue&amp;rdquo; to this day rather than the supposedly faster lock-free structure. The former reconnects
the channel to the memory model in &lt;a href="../../ch11sync/mem"&gt;11.9&lt;/a&gt;; the latter is a real trade-off about &amp;ldquo;how
correctness and maintainability win out over peak performance&amp;rdquo;.&lt;/p&gt;</description></item><item><title>10.7 Engineering Practice and Cross-Language Comparison</title><link>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/pattern/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://golang.design/under-the-hood/en/part3concurrency/ch10chan/pattern/</guid><description>&lt;h1 id="107-engineering-practice-and-cross-language-comparison"&gt;10.7 Engineering Practice and Cross-Language Comparison&lt;/h1&gt;
&lt;p&gt;The previous sections took the internal structure of a channel, the send and receive paths,
and the implementation of select all the way down. Once we understand the mechanism, a harder
and more engineering-flavored question follows: when should we use a channel, and when should we
not. Go&amp;rsquo;s slogan, &amp;ldquo;Do not communicate by sharing memory; instead, share memory by communicating,&amp;rdquo;
is easily read as &amp;ldquo;any shared state should go through a channel,&amp;rdquo; but that is not what its author
meant. This section reduces that slogan to an actionable rule of thumb, sets it against the lighter
tools in the chapter on synchronization primitives (&lt;a href="../../ch11sync/readme"&gt;Chapter 11&lt;/a&gt;),
and then places Go&amp;rsquo;s choice within the lineage of the CSP family, so we can understand its specific
coordinates in the design space.&lt;/p&gt;</description></item></channel></rss>