Skip to content
Newer
Older
100644 202 lines (185 sloc) 7.83 KB
4e64d7a @miekg nice epi
authored
1 \epi{%
2 \begin{itemize}
7811b5c @miekg Fix all the quotes and more [from: Stefan Schroeder]
authored
3 \item{``Parallelism is about performance;}
4 \item{Concurrency is about program design.''}
4e64d7a @miekg nice epi
authored
5 \end{itemize}%
531742a @jcs fix some typos
jcs authored
6 }{\textit{Google IO 2010}\\\textsc{ROB PIKE}}
a2a49ac @miekg more added
authored
7 \noindent{}In this chapter we will show off Go's ability for
91d2064 @miekg more stuff
authored
8 concurrent programming using channels and goroutines. Goroutines
9 are the central entity in Go's ability for concurrency. But what
f751142 @miekg Fixes from: Jonathan Kans
authored
10 \emph{is} a goroutine? From \cite{effective_go}:
7b26172 @miekg fix double page bib layout
authored
11 \begin{quote}
12 They're called goroutines because the existing terms --- threads, coroutines,
13 processes, and so on --- convey inaccurate connotations. A goroutine has a simple
91d2064 @miekg more stuff
authored
14 model: \emph{it is a function executing in parallel with other goroutines in the same
15 address space}. It is lightweight, costing little more than the allocation of
7b26172 @miekg fix double page bib layout
authored
16 stack space. And the stacks start small, so they are cheap, and grow by
17 allocating (and freeing) heap storage as required.
18 \end{quote}
d1746c7 @miekg more stuff added and fixed
authored
19 A \first{goroutine}{goroutine} is a normal function, except that you start
b2c0e4b @miekg add more text and explanation in channel chap
authored
20 it with the keyword \first{\key{go}}{keyword!go}.
21 \begin{lstlisting}
5a3f3b2 @dgryski sp: Tee -> Tea
dgryski authored
22 ready("Tea", 2) |\coderemark{Normal function call}|
23 go ready("Tea", 2) |\coderemark{\func{ready()} started as goroutine}|
b2c0e4b @miekg add more text and explanation in channel chap
authored
24 \end{lstlisting}
d1746c7 @miekg more stuff added and fixed
authored
25 The following idea for a program was taken from \cite{go_course_day3}.
26 We run a function as two goroutines, the goroutines wait for an amount of
f3af4be @miekg Again a batch of fixes from Filip
authored
27 time and then print something to the screen.
d1746c7 @miekg more stuff added and fixed
authored
28 On the lines 14 and 15 we start the goroutines.
b2c0e4b @miekg add more text and explanation in channel chap
authored
29 The \func{main} function
540fe24 @miekg more on concurrency added
authored
30 waits long enough, so that both goroutines will have printed their text. Right
df91f72 @miekg Cleanups
authored
31 now we wait for 5 seconds on line 17, but in fact we have no idea how
91d2064 @miekg more stuff
authored
32 long we should wait until all goroutines have exited.
a9803a6 @miekg small tweaks
authored
33 \lstinputlisting[numbers=right,label=src:sleeping,firstnumber=8,caption=Go routines in action,linerange={8,18}]{src/sleep.go}
34 Listing \ref{src:sleeping} outputs:
35 \begin{display}
5039c77 @miekg style changes and add small footnote about vars in Makefile
authored
36 I'm waiting \coderemark{Right away}
37 Coffee is ready! \coderemark{After 1 second}
5a3f3b2 @dgryski sp: Tee -> Tea
dgryski authored
38 Tea is ready! \coderemark{After 2 seconds}
a9803a6 @miekg small tweaks
authored
39 \end{display}
40
b2c0e4b @miekg add more text and explanation in channel chap
authored
41 If we did not wait for the goroutines (i.e. remove line 17) the program
d1746c7 @miekg more stuff added and fixed
authored
42 would be terminated immediately and any running goroutines would
43 \emph{die with it}.
a9803a6 @miekg small tweaks
authored
44 To fix this we need some kind of mechanism which allows us to
540fe24 @miekg more on concurrency added
authored
45 communicate with the goroutines. This mechanism is available
b5b4a11 @miekg Processed JC's command. chap 1 + 2 are now done
authored
46 to us in the form of \first{channels}{channels}. A
47 \first{channel}{channel} can be
b2c0e4b @miekg add more text and explanation in channel chap
authored
48 compared to a two-way pipe in Unix shells: you can send to and receive
540fe24 @miekg more on concurrency added
authored
49 values from it. Those values can only be of a specific type: the
adbd183 @miekg much more on channels and goroutines
authored
50 type of the channel. If we define a channel, we must also define the
d1746c7 @miekg more stuff added and fixed
authored
51 type of the values we can send on the channel. Note that we must use
52 \key{make} to create a channel:
adbd183 @miekg much more on channels and goroutines
authored
53 \begin{lstlisting}
54 ci := make(chan int)
55 cs := make(chan string)
56 cf := make(chan interface{})
57 \end{lstlisting}
58 Makes \var{ci} a channel on which we can send and receive integers,
59 makes \var{cs} a channel for strings and \var{cf} a channel for types
60 that satisfy the empty interface.
540fe24 @miekg more on concurrency added
authored
61 Sending on a channel and receiving from it, is done with the same operator:
d1746c7 @miekg more stuff added and fixed
authored
62 \lstinline{<-}. \index{operator!channel}
63 Depending on the operands it figures out what to do:
540fe24 @miekg more on concurrency added
authored
64 \begin{lstlisting}
65 ci <- 1 |\coderemark{\emph{Send} the integer 1 to the channel \var{ci}}|
66 <-ci |\coderemark{\emph{Receive} an integer from the channel \var{ci}}|
df91f72 @miekg Cleanups
authored
67 i := <-ci |\coderemark{\emph{Receive} from the channel \var{ci} and store it in \var{i}}|
540fe24 @miekg more on concurrency added
authored
68 \end{lstlisting}
a8b1e37 @dgryski sp: Lets -> Let's
dgryski authored
69 Let's put this to use.
4406d92 @miekg and fix the last 2 chapters
authored
70 \begin{lstlisting}[numbers=none,caption=Go routines and a channel,label=src:sleeping with channels]
7b26172 @miekg fix double page bib layout
authored
71 var c chan int |\longremark{Declare \var{c} to be a variable that is a %
d02c2fa @miekg fix prural of types (ints, strings) dont make the first part bold
authored
72 channel of ints. That is: this channel can move integers. Note %
540fe24 @miekg more on concurrency added
authored
73 that this variable is global so that the goroutines have access to it;}|
65c336c @miekg add more concurreny stuff
authored
74
7b26172 @miekg fix double page bib layout
authored
75 func ready(w string, sec int) {
df91f72 @miekg Cleanups
authored
76 time.Sleep(time.Duration(sec) * time.Second)
7b26172 @miekg fix double page bib layout
authored
77 fmt.Println(w, "is ready!")
78 c <- 1 |\longremark{Send the integer 1 on the channel \var{c};}|
79 }
65c336c @miekg add more concurreny stuff
authored
80
928d368 @miekg Again a batch of fixes from Filip
authored
81 func main() {
6dc0a22 @miekg more stuff
authored
82 c = make(chan int) |\longremark{Initialize \var{c};}|
5a3f3b2 @dgryski sp: Tee -> Tea
dgryski authored
83 go ready("Tea", 2) |\longremark{Start the goroutines with the keyword \key{go};}|
7b26172 @miekg fix double page bib layout
authored
84 go ready("Coffee", 1)
85 fmt.Println("I'm waiting, but not too long")
86 <-c |\longremark{Wait until we receive a value from the channel. Note that the value we receive is discarded;}|
87 <-c |\longremark{Two goroutines, two values to receive.}|
88 }
89 \end{lstlisting}
609a702 @miekg Make it work with a5paper
authored
90
7b26172 @miekg fix double page bib layout
authored
91 \showremarks
c29f528 @miekg Spell check
authored
92 There is still some remaining ugliness; we have to read twice from
540fe24 @miekg more on concurrency added
authored
93 the channel (lines 14 and 15). This is OK in this case, but what if
94 we don't know how many goroutines we started? This is where another
2ea7bef @miekg lower case keyword and package
authored
95 Go built-in comes in: \first{\key{select}}{keyword!select}. With \key{select} you
6dc0a22 @miekg more stuff
authored
96 can (among other things) listen for incoming data on a channel.
540fe24 @miekg more on concurrency added
authored
97
98 Using \key{select} in our program does not really make it shorter,
831a6af @dgryski prevent goroutine from being hypenated as gor-outine
dgryski authored
99 because we run too few go\-routines. We remove the lines 14 and 15 and
540fe24 @miekg more on concurrency added
authored
100 replace them with the following:
5a25657 @miekg Now style stuff in captions
authored
101 \begin{lstlisting}[caption=Using select,numbers=right,firstnumber=14]
540fe24 @miekg more on concurrency added
authored
102 L: for {
103 select {
104 case <-c:
105 i++
106 if i > 1 {
107 break L
108 }
109 }
110 }
111 \end{lstlisting}
df91f72 @miekg Cleanups
authored
112 We will now wait as long as it takes. Only when we have received more than
113 one reply on the channel \var{c} will we exit the loop \var{L}.
540fe24 @miekg more on concurrency added
authored
114
115 \subsection{Make it run in parallel}
0461fc7 @dgryski gr: concurrent -> concurrently
dgryski authored
116 While our goroutines were running concurrently, they were not running in
540fe24 @miekg more on concurrency added
authored
117 parallel. When you do not tell Go anything there can only be one
63a1bc7 @miekg tweaks
authored
118 goroutine running at a time. With \func{runtime.GOMAXPROCS(n)} you
119 can set the number of goroutines that can run in parallel. From
120 the documentation:
121 \begin{quote}
a537d58 @miekg small fixes
authored
122 GOMAXPROCS sets the maximum number of CPUs that can be executing
123 simultaneously and returns the previous setting. If n < 1, it does not
63a1bc7 @miekg tweaks
authored
124 change the current setting. \emph{This call will go away when the scheduler
125 improves.}
126 \end{quote}
a537d58 @miekg small fixes
authored
127 If you do not want to change any source code you can also set an
128 environment variable \verb|GOMAXPROCS| to the desired value.
6e5f8f5 @miekg some wicked marginpar testing
authored
129 %% test
130 %%\marginpar{%
131 %%$$\left\{
132 %%\begin{array}{l}
133 %%\parbox{2cm}{
134 %%hallo Yppp hallo Yppp hallo Yppp
135 %%hallo Yppp hallo Yppp hallo Yppp
136 %%hallo Yppp
137 %%}
138 %%\end{array}
139 %%\right.$$
140 %%}
a537d58 @miekg small fixes
authored
141
e9dcaa5 @miekg More on channels esp. buffered/unbufferd
authored
142 %%\section{So many channels and still \ldots}
143 \section{More on channels}
144 \label{sec:more on channels}
145 When you create a channel in Go with \lstinline{ch := make(chan bool)},
146 an \first{unbuffered channel}{channel!unbuffered} for
147 bools is created. What does this mean for your program? For one, if you
148 read (\lstinline{value := <-ch}) it will block until there is data to
149 receive. Secondly anything sending (\lstinline{ch<-5}) will block until there
150 is somebody to read it.
5c25b47 @miekg Spell check
authored
151 Unbuffered channels make a perfect tool for synchronizing multiple
e9dcaa5 @miekg More on channels esp. buffered/unbufferd
authored
152 goroutines.
153 \index{channel!blocking read}
154 \index{channel!blocking write}
155
156 But Go allows you to specify the buffer size of
0ef8c65 @dgryski sp: simple -> simply
dgryski authored
157 a channel, which is quite simply how many elements a channel can hold.
166335f @dgryski gr: we're only talking about one channel.
dgryski authored
158 \lstinline{ch := make(chan bool, 4)}, creates a buffered channel of
159 bools that can hold 4 elements. The first 4 elements in this channel
e9dcaa5 @miekg More on channels esp. buffered/unbufferd
authored
160 are written without any blocking.
161 When you write the 5$^{th}$ element, your
162 code \emph{will} block, until another goroutine reads some elements from the
163 channel to make room.
164 \index{channel!non-blocking read}
165 \index{channel!non-blocking write}
166
167 In conclusion, the following is true in Go:
168 $$
169 \textrm{\lstinline{ch := make(chan type, value)}}
170 \left\{
171 \begin{array}{ll}
f88cde2 @miekg Fix closing of channels
authored
172 value == 0 & \rightarrow \textrm{unbuffered)} \\
173 value > 0 & \rightarrow \textrm{buffer \emph{value} elements}
e9dcaa5 @miekg More on channels esp. buffered/unbufferd
authored
174 \end{array}
175 \right.
176 $$
177
178 \subsection{Closing channels}
f88cde2 @miekg Fix closing of channels
authored
179 When a channel is closed the reading side needs to know this.
180 The following code will check if a channel is closed.
181 \begin{lstlisting}
182 x, ok = <-ch
183 \end{lstlisting}
184 Where \lstinline{ok} is set to \lstinline{true} the channel is not closed
185 \emph{and} we've read something.
186 Otherwise \var{ok} is set to \lstinline{false}. In that case the channel
187 was closed.
188
b54c75e @miekg add new section
authored
189 \subsection{Read-only or write-only channels}
190
191
f88cde2 @miekg Fix closing of channels
authored
192 \todo{more needs to be written}
e9dcaa5 @miekg More on channels esp. buffered/unbufferd
authored
193
164f7a7 @miekg start new repo
authored
194 \section{Exercises}
195 \input{ex-channels/ex-for-channels.tex}
196
7fcac65 @miekg Move around the fibonaci exercise and add one in channels chapter
authored
197 \input{ex-channels/ex-fib.tex}
198
164f7a7 @miekg start new repo
authored
199 \cleardoublepage
200 \section{Answers}
201 \shipoutAnswer
Something went wrong with that request. Please try again.