[go-nuts] goroutines execute in the same address space

402 views
Skip to first unread message

Loa Lind

unread,
May 9, 2010, 5:05:23 AM5/9/10
to golang-nuts
What does it mean that goroutines execute in the same address space?

"They're called goroutines because the existing terms—threads,
coroutines, processes, and so on—convey inaccurate connotations. A
goroutine has a simple model: it is a function executing in parallel
with other goroutines in the same address space. It is lightweight,
costing little more than the allocation of stack space. And the stacks
start small, so they are cheap, and grow by allocating (and freeing)
heap storage as required." http://golang.org/doc/effective_go.html

⚖ Alexander "Surma" Surma

unread,
May 9, 2010, 5:27:57 AM5/9/10
to Loa Lind, golang-nuts
It means that goroutines share their memory and you can therefore pass
pointers from one goroutine to another without causing a access
violation.

Surma

Loa Lind

unread,
May 9, 2010, 5:33:46 AM5/9/10
to golang-nuts
Thank you that makes sense :)

On 9 Maj, 11:27, ⚖ Alexander "Surma" Surma

Russel Winder

unread,
May 9, 2010, 6:14:52 AM5/9/10
to ⚖ Alexander "Surma" Surma, Loa Lind, golang-nuts
Alexander,

But note that to use shared memory is invariably the wrong thing to do
-- just because you can do something doesn't mean you should.

Shared-memory multithreading may be a reasonable underlying
infrastructure for realizing parallel systems frameworks, but it is the
wrong model for applications programmers to work with. You should
always use a higher-level model, cf. actor model, CSP, dataflow, data
parallelism. It is worth noting that all programming languages except C
-- i.e. C++, Java, Scala, Erlang, Clojure, Python, and of course Go --
are moving to providing higher-level architecture frameworks over
threading exactly because it is the right thing to do.
--
Russel.
=============================================================================
Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel...@ekiga.net
41 Buckmaster Road m: +44 7770 465 077 xmpp: rus...@russel.org.uk
London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder

signature.asc

chris dollin

unread,
May 9, 2010, 6:20:05 AM5/9/10
to Russel Winder, ⚖ Alexander "Surma" Surma, Loa Lind, golang-nuts
2010/5/9 Russel Winder <rus...@russel.org.uk>

Alexander,

On Sun, 2010-05-09 at 11:27 +0200, ⚖ Alexander "Surma" Surma wrote:
> It means that goroutines share their memory and you can therefore pass
> pointers from one goroutine to another without causing a access
> violation.

But note that to use shared memory is invariably the wrong thing to do
-- just because you can do something doesn't mean you should.

"Invariably" surely overstates the case.

* the pointer may refer to an immutable object.

* the pointer may be the responsibility of a single goroutine at
   a time

Chris

--
Chris "never say never, again" Dollin

⚖ Alexander "Surma" Surma

unread,
May 9, 2010, 6:25:53 AM5/9/10
to chris dollin, Russel Winder, Loa Lind, golang-nuts
Sure, you should not just share memory and see what happens. There's
gotta be some enforcements for safety.
However, that fact is not included in the definition of "running in
the same memory space", now is it?

Surma

Russel Winder

unread,
May 9, 2010, 7:02:26 AM5/9/10
to chris dollin, ⚖ Alexander "Surma" Surma, Loa Lind, golang-nuts
On Sun, 2010-05-09 at 11:20 +0100, chris dollin wrote:
> 2010/5/9 Russel Winder <rus...@russel.org.uk>
> Alexander,
>
> On Sun, 2010-05-09 at 11:27 +0200, ⚖ Alexander "Surma" Surma
> wrote:
> > It means that goroutines share their memory and you can
> therefore pass
> > pointers from one goroutine to another without causing a
> access
> > violation.
>
> But note that to use shared memory is invariably the wrong
> thing to do
> -- just because you can do something doesn't mean you should.
>
> "Invariably" surely overstates the case.

Yes and no. Amongst programmers who know what they are doing, and are
thinking as they code, clearly this is an overstatement. However,
sadly, it is all too difficult to overestimate the incompetence of the
average programmer, especially when it comes to issues relating to
concurrency and parallelism.

> * the pointer may refer to an immutable object.
>

Immutable is good, especially in a concurrent and parallel system
context.


>
> * the pointer may be the responsibility of a single goroutine at
> a time
>

Ownership issues tend to be the biggest problems in C, C++, Java, . . .
the question is whether there is only a single owner even in the case
where you think there is.

signature.asc

Russel Winder

unread,
May 9, 2010, 7:02:27 AM5/9/10
to ⚖ Alexander "Surma" Surma, chris dollin, Loa Lind, golang-nuts

Definitely not. Erlang has shown that harnessing actor model/CSP is a
good way of structuring single memory space systems (*). Which is (I
infer from the documentation) the inspiration behind goroutines and the
reason they are the way they are.

(*) Whether PGAS, e.g. Chapel, X10, Fortress, ever takes hold is a moot
point.

signature.asc

Russ Cox

unread,
May 9, 2010, 12:45:07 PM5/9/10
to Russel Winder, golang-nuts
>> * the pointer may be the responsibility of a single goroutine at
>>    a time
>>
> Ownership issues tend to be the biggest problems in C, C++, Java, . . .
> the question is whether there is only a single owner even in the case
> where you think there is.

Yes, but those languages have no idiomatic way to convey ownership,
and condition variables are so awkward as to be avoided whenever possible.
A very common idiom in Go is to send a pointer on a channel to to
another goroutine, which by convention usually indicates that the
receiving goroutine is, for now, the owner of the pointed-at data.

> Erlang has shown that harnessing actor model/CSP is a
> good way of structuring single memory space systems (*). Which is (I
> infer from the documentation) the inspiration behind goroutines and the
> reason they are the way they are.

The inspiration behind goroutines is the lineage from Limbo to Alef
to Newsqueak to CSP. Erlang is based on CSP too but was not a
direct influence (in particular, Erlang doesn't even have the concept
of a channel!).

Russ

Russel Winder

unread,
May 9, 2010, 1:13:11 PM5/9/10
to r...@golang.org, golang-nuts
On Sun, 2010-05-09 at 09:45 -0700, Russ Cox wrote:
[ . . . ]

> Yes, but those languages have no idiomatic way to convey ownership,
> and condition variables are so awkward as to be avoided whenever possible.
> A very common idiom in Go is to send a pointer on a channel to to
> another goroutine, which by convention usually indicates that the
> receiving goroutine is, for now, the owner of the pointed-at data.

"by convention usually" presumably means that there is no barrier to
misusing or misunderstanding, leading to serious errors? Again, not a
problem for good programmers, but a potential minefield for average and
poor programmers.


> > Erlang has shown that harnessing actor model/CSP is a
> > good way of structuring single memory space systems (*). Which is (I
> > infer from the documentation) the inspiration behind goroutines and the
> > reason they are the way they are.
>
> The inspiration behind goroutines is the lineage from Limbo to Alef
> to Newsqueak to CSP. Erlang is based on CSP too but was not a
> direct influence (in particular, Erlang doesn't even have the concept
> of a channel!).

Given the reported dates of appearance of the languages I am thinking
your lineage isn't quite right. I am guessing that Newsqueak and Limbo
used ideas from CSP and Alef used ideas from Newsqueak and Limbo. And
thence to Go. However, I am sure Rob can put us right.

occam really needs to appear somewhere at the beginning of that list of
antecedants of Go?

signature.asc

Russ Cox

unread,
May 9, 2010, 2:27:46 PM5/9/10
to Russel Winder, golang-nuts
> "by convention usually" presumably means that there is no barrier to
> misusing or misunderstanding, leading to serious errors?  Again, not a
> problem for good programmers, but a potential minefield for average and
> poor programmers.

I find it very refreshing to be working in a language that provides
useful tools and trusts the programmer to use them well, in contrast
to languages like Java that only reluctantly provide safety scissors
and clearly regret even that.

There are lots of conventions in Go. The fact that a method with
the signature Read([]byte) (int, os.Error) reads from an input stream
is a convention too, with no barrier to misuse or misunderstanding.
It is incredibly powerful, and at least some of that power comes from
relying entirely on convention. Go would simply not be usable
if every type with a Read method had to say "implements io.Reader"
somewhere in its declaration: it doesn't scale.

As for ownership conventions, there is a growing body of anecdotal
evidence that programmers can write correct concurrent code in Go
easily, without the misunderstandings you fear, even programmers
who have not written parallel code before in other languages.
(Perhaps they are the best suited to it, since they don't have to
unlearn the complexity of mutexes and condition variables.)

>> > Erlang has shown that harnessing actor model/CSP is a
>> > good way of structuring single memory space systems (*).  Which is (I
>> > infer from the documentation) the inspiration behind goroutines and the
>> > reason they are the way they are.
>>
>> The inspiration behind goroutines is the lineage from Limbo to Alef
>> to Newsqueak to CSP.  Erlang is based on CSP too but was not a
>> direct influence (in particular, Erlang doesn't even have the concept
>> of a channel!).
>
> Given the reported dates of appearance of the languages I am thinking
> your lineage isn't quite right.

The lineage is in reverse chronological order.
I did forget one step: it should be Newsqueak to Squeak to CSP.

> occam really needs to appear somewhere at the beginning of that list of
> antecedants of Go?

I wasn't there, but my understanding is that Occam and Squeak
simply share a common ancestor (CSP).

Russ

Rob 'Commander' Pike

unread,
May 9, 2010, 4:05:10 PM5/9/10
to r...@golang.org, Russel Winder, golang-nuts
Russ's historical analysis is right, except that there were two CSPs. The original 1978 paper did not have channels; the later book did. Newsqueak was the first programming language I ever used that had channels, but that is not a claim of invention. I honestly have no memory of where idea for channels in Newsqueak came from, but I'm pretty sure I didn't see the CSP book until afterwards. I do have a vivid memory of getting the idea for the implementation of hyperthreading in Newsqueak by generalizing something I read in the HUB paper by O'Dell, which was based on much earlier work by Masamoto; that was the trigger to write the language. Winterbottom grafted Newsqueak's communication ideas onto a C-like systems language to create Alef. Limbo arrived when it was time to build a virtual machine for embedded processing.

Neither Occam nor Erlang influenced those languages. I didn't learn much about Occam until after Newqueak, and about Erlang until after Limbo. It was a long time ago but I believe I ignored Occam primarily because of its lack of first-class channels; its roots in hardware did not enable that generality.

That ignorance was repaid. I don't believe the concurrent programming language community knows much about Newsqueak.

-rob

Anupam Kapoor

unread,
May 10, 2010, 12:40:48 AM5/10/10
to r...@golang.org, Russel Winder, golang-nuts
Russ Cox <rsc@golang> wrote:
,----
| > Erlang is based on CSP too but was not a
| > direct influence (in particular, Erlang doesn't even have the concept
| > of a channel!).
`----
that is correct. however erlang does provide mechanisms for
sending/receiving messages to erlang-processes running within the
erlang-vm. messages can be arbitrary erlang types (afaik)

which brings up another question: erlang, uniquely identifies processes
by a 'Pid'. is there a similar notion for goroutines ?

kind regards
anupam


This email and any attachments may contain legally privileged and/or confidential information of Starent Networks, Corp. and is intended only for the individual or entity named in the message. The information transmitted may not be used to create or change any contractual obligations of Starent Networks, Corp. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this e-mail and its attachments by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify the sender immediately -- by replying to this message or by sending an email to postm...@starentnetworks.com -- and destroy all copies of this message and any attachments without reading or disclosing their contents. Thank you.

Russ Cox

unread,
May 10, 2010, 12:58:02 AM5/10/10
to Anupam Kapoor, Russel Winder, golang-nuts
> which brings up another question: erlang, uniquely identifies processes
> by a 'Pid'. is there a similar notion for goroutines ?

There isn't a Pid but I would argue that channels
are the equivalent notion in Go, because they are
how you identify a communication.

Russ

Russel Winder

unread,
May 10, 2010, 3:41:44 AM5/10/10
to r...@golang.org, golang-nuts
On Sun, 2010-05-09 at 11:27 -0700, Russ Cox wrote:
[ . . . ]
> I find it very refreshing to be working in a language that provides
> useful tools and trusts the programmer to use them well, in contrast
> to languages like Java that only reluctantly provide safety scissors
> and clearly regret even that.

There is an interesting tension here. I think it is well accepted that
good programmers prefer power and flexibility at the cost of safety
support and still get things right (with some errors obviously :-) Weak
and poor programmers though are generally unable to survive with the
same languages, even if they think they are doing. Clearly there is no
one answer to this conundrum, at least not yet.

> There are lots of conventions in Go. The fact that a method with
> the signature Read([]byte) (int, os.Error) reads from an input stream
> is a convention too, with no barrier to misuse or misunderstanding.
> It is incredibly powerful, and at least some of that power comes from
> relying entirely on convention. Go would simply not be usable
> if every type with a Read method had to say "implements io.Reader"
> somewhere in its declaration: it doesn't scale.

Convention over configuration has become a big win in build and
configuration management. Again though with power and flexibility comes
responsibility. Weak and poor staff tend to be unable or unwilling to
face up to the responsibility.

Personally I have no problem aiming for using only the best -- hire 1/3
the number of staff, pay them 3 times as much, and get twice the amount
of work done per unit time. But this only works using flexible,
powerful, expressive languages that are usable.

> As for ownership conventions, there is a growing body of anecdotal
> evidence that programmers can write correct concurrent code in Go
> easily, without the misunderstandings you fear, even programmers
> who have not written parallel code before in other languages.
> (Perhaps they are the best suited to it, since they don't have to
> unlearn the complexity of mutexes and condition variables.)

I am finding that as soon as organizations use actors, CSP, dataflow or
data parallelism instead of shared-memory multithreading (with locks,
mutexes, etc.) as the only acceptable way of developing parallel
applications, many more of the programming staff are able to cope with
concurrency and parallelism. Anecdotal evidence only I'm afraid, but
very indicative of the potentially right way forward.

[ . . . ]

> The lineage is in reverse chronological order.
> I did forget one step: it should be Newsqueak to Squeak to CSP.
>
> > occam really needs to appear somewhere at the beginning of that list of
> > antecedants of Go?
>
> I wasn't there, but my understanding is that Occam and Squeak
> simply share a common ancestor (CSP).

Rob has chipped in here . . .

signature.asc

Russel Winder

unread,
May 10, 2010, 3:51:57 AM5/10/10
to Rob 'Commander' Pike, r...@golang.org, golang-nuts
Rob,

On Sun, 2010-05-09 at 13:05 -0700, Rob 'Commander' Pike wrote:
> Russ's historical analysis is right, except that there were two CSPs.
> The original 1978 paper did not have channels; the later book did.
> Newsqueak was the first programming language I ever used that had
> channels, but that is not a claim of invention. I honestly have no
> memory of where idea for channels in Newsqueak came from, but I'm
> pretty sure I didn't see the CSP book until afterwards. I do have a
> vivid memory of getting the idea for the implementation of
> hyperthreading in Newsqueak by generalizing something I read in the
> HUB paper by O'Dell, which was based on much earlier work by Masamoto;
> that was the trigger to write the language. Winterbottom grafted
> Newsqueak's communication ideas onto a C-like systems language to
> create Alef. Limbo arrived when it was time to build a virtual
> machine for embedded processing.

Thanks for chipping in these recollections. Most interesting. I think
it would be useful to get some of the "historians of computing" to
collate as many as possible of snippets such as this to add to the
modeling of the history of programming languages from c1950 onwards.


>
> Neither Occam nor Erlang influenced those languages. I didn't learn
> much about Occam until after Newqueak, and about Erlang until after
> Limbo. It was a long time ago but I believe I ignored Occam primarily
> because of its lack of first-class channels; its roots in hardware did
> not enable that generality.

I think that there being parallel independent development of essentially
similar ideas is both useful and indicative that the ideas are likely to
be important. cf. calculus, differential geometry/gauge theories,
virtual machines, channels, etc.

>
> That ignorance was repaid. I don't believe the concurrent programming
> language community knows much about Newsqueak.

I think you are right. Certainly the HPC community don't. They appear
to have a problem seeing beyond MPI and OpenMP.

signature.asc

Jesper Louis Andersen

unread,
May 10, 2010, 4:04:02 AM5/10/10
to r...@golang.org, Anupam Kapoor, Russel Winder, golang-nuts
Exactly my experience. The Communication-by-process (CBP) can easily
simulate Communication-by-channel (CBC) and vice versa, so none of
them "wins" per se.

If your language is statically typed, channels are the way to go. You
can give a process a big sum type (it receiver an integer OR a string)
- but it quickly gets unwieldy to work with. Worse, unless you really
crank up the type system, obvious bugs won't get caught by it. A
channel on the other hand is a neat coat-hanger for for the type
system.

If a goroutine only waits on a single channel out of the 4 it has
access to, it only needs to be woken up when that channel fires. In
Erlang, you have to reconsider any incoming message to see if it fits
with the pattern. Both methods have some optimizations, but I'd argue
that channels are simpler to optimize. Note that if you only have a
single channel, the construction akin to the 'select' in Go becomes
extremely important. Hence you need to equivalent of guards on the
channel: "Hand me the first message in FIFO order matching this
pattern".

A channel encodes a capability, authorizing you to send certain kinds
of messages. In CBP, the process PID is the capability. It is an coin
in the chest on the principle of "Make illegal states
unrepresentable". If you don't hold access to the capability, you
can't possibly use it.

Constructing communication networks is completely different. In CBP
you have to propagate the knowledge of PIDs, whereas in CBC it is
channels. I think there are subtle semantic differences when
processes/goroutines exits as the channel can be handed on; the PID
cannot. Erlang defines global registration of processes because of
this.

In a distributed setting, a Pid on Node X has an obvious ownership.
Node X owns that PID. In a channel world, one must figure out how
channels are distributed among nodes. An important part is to
acknowledge the possibility of failure in the network, or by someone
taking a hammer to one node. Erlang circumvents the problem: A PIDs
mailbox queue is unbounded and as a result, a send never fails. A
message is not guaranteed to arrive on inter-node sends however, so
one must implement the basics of ACK'ing with timeouts to ensure
progress.

In the CBC methodology, there is more values to juggle. Since it is
custom to give a goroutine more than one channel to work on, you will
have to keep track of multiple channels and what types they can
receive. Go's lack of a (non-recursive) algebraic datatypes
(essentially a tagged union), may suggest you end up with considerably
more channels compared to, say, Haskell's concurrency (which, among
other things, contains a channel communication primitive).

--
J.

Carl

unread,
May 10, 2010, 4:37:48 PM5/10/10
to golang-nuts
Thanks for the backgrounder, thats a really good one. While I am still
trying to get my head around channels (the concept) and I was able to
understand the concept behind CSP and the evolution to Golang better
now.

How does a channel compare to a pipe, or is it essentially the same
thing? (in most simple terms).

I think for illustration purposes it might be useful to use the pipe
and garden hose analogy, although I don't know enough about Channels
to know if that is appropriate.

At the end of the day, ideally you would not actually be
"programming" that much anymore you would be spending a lot of time
doing "plumbing".

I think this is what people more or less have in mind when they are
talking about "dataflow programming".

I could be wrong though.

Carl

roger peppe

unread,
May 10, 2010, 4:54:41 PM5/10/10
to Carl, golang-nuts
On 10 May 2010 21:37, Carl <2ca...@googlemail.com> wrote:
> How does a channel compare to a pipe, or is it essentially the same
> thing? (in most simple terms).

you can only send bytes down a pipe, but you can send
any object down a channel. also, a pipe is buffered,
whereas a channel in its default mode is not.

another difference is that when you create a pipe,
you get a handle for each end, but with a channel,
you use the same object for both reading and writing.

winston

unread,
May 11, 2010, 6:36:24 AM5/11/10
to golang-nuts
>
> Neither Occam nor Erlang influenced those languages.  I didn't learn much about Occam until after Newqueak, and about Erlang until after Limbo.  It was a long time ago but I believe I ignored Occam primarily because of its lack of first-class channels; its roots in hardware did not enable that generality.
>
Just curious what you mean by occam's lack of first class channels.

roger peppe

unread,
May 11, 2010, 7:05:56 AM5/11/10
to winston, golang-nuts
On 11 May 2010 11:36, winston <kod...@gmail.com> wrote:
> Just curious what you mean by occam's lack of first class channels.

in occam 2, all channels were created statically - you could not
create new channels (or processes) at runtime; neither could you store
channels in
data structures or send them as values down other channels.

this was in keeping with occam's goal of being a language that
could map directly to hardware. (it had no recursive functions either).

if you're interested, google for "occam reference manual".

snim2

unread,
May 14, 2010, 9:40:39 AM5/14/10
to golang-nuts
On May 11, 12:05 pm, roger peppe <rogpe...@gmail.com> wrote:
> On 11 May 2010 11:36, winston <kod...@gmail.com> wrote:
>
> > Just curious what you mean by occam's lack of first class channels.
>
> in occam 2, all channels were created statically - you could not
> create new channels (or processes) at runtime; neither could you store
> channels in
> data structures or send them as values down other channels.
>
> this was in keeping with occam's goal of being a language that
> could map directly to hardware. (it had no recursive functions either).
>

This has changed somewhat in recent years. OCCAM-pi, from Peter
Welch's group at Kent, is intended to mix OCCAM with Robin Milner's
\pi-calculus. In the \pi-calculus (unlike Hoare's CSP and Milner's
CCS) channels are "first-class" in the sense that a channel can be
transmitted between processes, in the same way that any object may be
sent between processes via channels. This allows for run-time rewiring
of a network of running processes, which is important in fields like
pervasive and mobile computing.

The OCCAM-pi site is here, if you're interested:

http://www.cs.kent.ac.uk/projects/ofa/kroc/

Sarah

roger peppe

unread,
May 14, 2010, 9:50:42 AM5/14/10
to snim2, golang-nuts
that's interesting, thanks.
things have moved on a bit from transputers in 1993 :-)
Reply all
Reply to author
Forward
0 new messages