Hacker News new | ask | show | jobs
by jrockway 1985 days ago
I think it's necessary to leak the details of the mutex until you have some sort of transaction object to abstract that away. In a concurrent workload, these two things are different:

   store.Lock()
   store.WriteKey("foo", "bar")
   x := store.ReadKey("foo")
   store.Unlock()
   // x is always "bar"
And:

   store.Lock()
   store.WriteKey("foo", "bar")
   store.Unlock()

   store.Lock()
   x := store.ReadKey("foo")
   store.Unlock()
   // x could be whatever another goroutine set "foo" to, not the "bar" that you just wrote.
In a more complicated app, you'll have library that acts as the datastore, with transaction objects that abstract away the actual mutex (which will be something more complicated):

   var x string
   err := db.DoTx(func(tx *Tx) {
     tx.Write("foo", "bar")
     x = tx.Read("foo")
   })
   if err != nil { ... }
   // what x is depends on the details of your database; maybe you're running at "read uncommitted", maybe you're running at "serializable".
But, even in the simple examples, it's worth thinking about the difference between lock { write; read } and lock { write }; lock { read }.