garbage collection: maps and channels

2,008 views
Skip to first unread message

ab

unread,
Feb 7, 2013, 10:48:11 AM2/7/13
to golan...@googlegroups.com
Hello there,

I have question regarding garbage collecting.
Suppose I have a map of channels because I want to open one channel per "record" (let's say a record is an object with a changing state) in order to queue the changes of state (I use a channel of buffer size 1 as a semaphore).
The function is called within a set of goroutines so I don't know when it is going to be called nor by which goroutine.
The point is that most channels don't need to be opened all the time, a record could change state once a year, whereas another could change state every minute. But I have no idea of that so I cannot explicitely close the channels.
And I can have a lot of "records" so I don't want to keep all of them opened.

Here is the current code:

 1. var channels map[string] chan int = make(map[string] chan int)
 2.
 3. func WithinAGoRoutine(b key) error {
 4.     c, ok := channels[b]
 5.     if !ok {
 6.         channels[b] = make(chan int, 1)
 7.         c = channels[b]
 8.     }
 9.     var err error = nil
10.     c <- 1
11.     err = process()
12.     <- cs
13.     return err
14. }

So, my question is, how does the garbage collector deals with that?
What happens if I delete the channel from the map but it is still receiving data?
What happens if a goroutine closes the channel just when a new goroutine is between line 4 and 5? ok is true but the channel is closed before the new goroutine uses it.


Maybe using channels is not the good option for what I want and I'd be happy to read your suggestions, but anyway I'd like to know how the garbage collector handles that!

Thanks.

Cheers,
Anthony

Matt Kane's Brain

unread,
Feb 7, 2013, 11:18:05 AM2/7/13
to ab, golan...@googlegroups.com
On Thu, Feb 7, 2013 at 10:48 AM, ab <cid...@gmail.com> wrote:
> What happens if I delete the channel from the map but it is still receiving
> data?

The channel will not be garbage collected until there are no more
references to it.

> What happens if a goroutine closes the channel just when a new goroutine is
> between line 4 and 5? ok is true but the channel is closed before the new
> goroutine uses it.

The send will panic.

--
matt kane's brain
twitter: the_real_mkb / nynexrepublic
http://hydrogenproject.com

minux

unread,
Feb 7, 2013, 11:31:17 AM2/7/13
to ab, golan...@googlegroups.com
On Thu, Feb 7, 2013 at 11:48 PM, ab <cid...@gmail.com> wrote:
I have question regarding garbage collecting.
Suppose I have a map of channels because I want to open one channel per "record" (let's say a record is an object with a changing state) in order to queue the changes of state (I use a channel of buffer size 1 as a semaphore).
The function is called within a set of goroutines so I don't know when it is going to be called nor by which goroutine.
The point is that most channels don't need to be opened all the time, a record could change state once a year, whereas another could change state every minute. But I have no idea of that so I cannot explicitely close the channels.
And I can have a lot of "records" so I don't want to keep all of them opened.

Here is the current code:

 1. var channels map[string] chan int = make(map[string] chan int)
 2.
 3. func WithinAGoRoutine(b key) error {
 4.     c, ok := channels[b]
 5.     if !ok {
 6.         channels[b] = make(chan int, 1)
 7.         c = channels[b]
 8.     }
 9.     var err error = nil
 
10.     c <- 1
11.     err = process()
12.     <- cs
13.     return err
14. }

So, my question is, how does the garbage collector deals with that?
What happens if I delete the channel from the map but it is still receiving data?
as long as at least one goroutine keep reference to a channel, it won't be collected. 
What happens if a goroutine closes the channel just when a new goroutine is between line 4 and 5? ok is true but the channel is closed before the new goroutine uses it.
this is a data race.
that new goroutine will panic (writing to closed channel), you really shouldn't close the
channel at the receive goroutine without proper synchronization with all the potential
senders.

John Nagle

unread,
Feb 7, 2013, 6:44:37 PM2/7/13
to golan...@googlegroups.com
Channel closeout in the multiple-senders case is rather messy.
You have to avoid closing twice, and avoid getting the receiver
hung waiting on a channel with no senders left. This takes
some extra coordination.

You can use the wait group mechanism to track the exiting of
all the senders. Before the "go", do an "w.Add". In the goroutine,
do a "defer w.Done()", so the count goes down when the goroutine
exits, no matter how it does it. Then have an extra goroutine which
does the "w.Wait()" on the wait group. It just closes the channel and
exits. The receiver on the main channel then sees the channel EOF,
and the receiver knows everybody is done.

Bear in mind that maps are not thread-safe. If you store into
a map from one goroutine and read it from another, you must put
mutex locks around the map accesses.

John Nagle



ab

unread,
Feb 8, 2013, 4:27:52 AM2/8/13
to golan...@googlegroups.com
Hello,

Thank you all for your replies. Globally, that is what I intuited!

Thank you for the reminder about maps too, I'll add a mutex.
Reply all
Reply to author
Forward
0 new messages