Oh, thank you. I think RWMutex is exactly what I'm looking for. The whole channel thing was really nice when I was just dropping things onto them and moving on, but I think just moving to a mutex is going to be better going forward. Plus, it will allow simultaneous reads.
My experience with the case of "many" readers is that the channel way is harder and can risk not being as effective as using a mutex.
So, I've got this struct which contains a map and which is accessed from many goroutines. It's also go a bunch of channels and a select on those channels. So, if you want something done with this map, you just put a message on the proper channel. This works great when you don't need a response, but when you want to do something like, say, get some subset of keys from the map, you have to put your own channel on a channel, then wait on it for a response. That seems at least as messy as just globally locking on the map. I'm just wondering if maybe there's a cleaner way to go about this? Is it something that comes up often? Thanks!
Whenever you have writers you need to either lock, or all readers need to be aware of the writes so they don't clash. If you want to use multiple channels instead of mutexes, i typically create an array of channels equal to the number of CPU's and then use a modulus of the key to decide which channel to send to. So if you have 8 CPU's, you would create 8 channels. For each read/write you do "key%8" and then put it on that numbered channel. All those channels can read/write concurrently and they'll never clash on the same element. The throughput is very high.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Interesting. Yeah i agree buckets makes a lot of sense. In my case i didn't think to do that as i had other operations afterwards that would then take the map and sort it, so multiple buckets would be more expensive merge/sort.
On Saturday, February 2, 2013 12:02:07 AM UTC-6, Hamish Ogilvy wrote:Interesting. Yeah i agree buckets makes a lot of sense. In my case i didn't think to do that as i had other operations afterwards that would then take the map and sort it, so multiple buckets would be more expensive merge/sort.
Not sure if we are defining bucket the same way.
Each bucket group has a slice of struct { key/value } (aka bucket).
The slice index is picked by the lower X bits of the hashed key.
Ok got you. I thought we were still talking maps. All good. In the case I was talking about, my map keys were very sparse, so various solutions i tried based on slices all ended up with more overhead to get around that.
On 2/2/2013 12:21 PM, bryanturley wrote:
>
>
> On Saturday, February 2, 2013 2:01:06 PM UTC-6, John Nagle wrote:
>>
>> On 2/2/2013 10:58 AM, bryanturley wrote
>> > http://play.golang.org/p/adcY5LdTyj <-- done flag example.
>>
>> If the "work" parameter there actually did anything, you'd have
>> a race condition. The input parameter to four instances of a
>> goroutine is the same shared slice.
>>
>> John Nagle
>>
>
> Nice avoidance. It wasn't about the work it was about the mutex, channel.
> The work slice was just representative.
Here's the program written using Add/Done/Wait, which is the
appropriate pattern for this case.
If you're not sending data over channels, channels don't do much.
They're really just two counted semaphores, a counter, and a
buffer. Read C.A. Hoare's classic paper from 1974
http://www.matematicas.unam.mx/jloa/Articulos/CARHoareMonitors.pdf
where these concepts were first introduced. Example 4 describes
a Go channel.
John Nagle