Reputation: 25
My Golang code gets different records from the database using goroutines, and increments the value in a determinated field in the record.
I can avoid the race condition If I use Mutex or Channels, but I have a bottleneck because every access to the database waits until the previous access is done.
I think I should do something like one Mutex for every different record, instead one only Mutex for all.
How could I do it?
Thanks for any reply.
Upvotes: 0
Views: 833
Reputation: 43909
In the comments you said you are using Couchbase. If the record you wish to update consists of only an integer, you can use the built in atomic increment functionality with Bucket.Incr
.
If the value is part of a larger document, you can use the database's "Check and Set" functionality. In essence, you want to create a loop that does the following:
Bucket.Gets
Bucket.Cas
, passing the CAS value retrieved in (1).Note that it is important to retrieve the document fresh each time in the loop. If the update fails due to an incorrect CAS value, it means the document was updated between the read and the write.
Upvotes: 1
Reputation: 2450
If the database has a way of handling that (i.e. an atomic counter built in) you should use that. If not, or if you want to do this in go, you can use buffered channels. Inserting to a buffered channel is not blocking unless the buffer is full.
then, to handle the increments one at a time, in a goroutine you could have something like
for{
select{
value, _ := <-CounterChan
incrementCounterBy(value)
}
}
Upvotes: 0