ConcurrentProgrammingWithGo
ConcurrentProgrammingWithGo copied to clipboard
Chatper 6 - Excersie 2 - Doubt
In previous chapters, we saw the TryLock() operation on mutexes. This is a nonblocking call that returns immediately without waiting. If the lock is not available, the function returns false; otherwise, it locks the mutex and returns true. Can you write a similar non-blocking function called TryWait() on our implementation of a waitgroup from listing 6.8? This function will return immediately with false if the waitgroup is not done; otherwise, it returns true.
From my understanding is that TryWait
should not block if the waitgroup is not done but the solution for it is
func (wg *WaitGrp) TryWait() bool {
wg.cond.L.Lock()
result := wg.groupSize == 0
wg.cond.L.Unlock()
return result
}
> wg.cond.L.Lock()
Doesn't this line block the current goroutine until it got exclusive access to cond.L
mutex ?
Event though cond.L
mutex is internal and get's blocked only for short time by these methods Add, Done, Wait
. I was hoping we can implement a solution similar to Excerise 4.3 . Where we implement TryReadLock
for our mutex.
Sharing solution for reference
func (rw *ReadWriteMutex) TryReadLock() bool {
if rw.readersLock.TryLock() {
globalSuccess := true
if rw.readersCounter == 0 {
globalSuccess = rw.globalLock.TryLock()
}
if globalSuccess {
rw.readersCounter++
}
rw.readersLock.Unlock()
return globalSuccess
} else {
return false
}
}
Anyways my doubt is that is there any way to implement TryWait
without waiting for cond.L.Lock
too ?
Hi there, Thank you for your question and for buying the book. The TryWait() implementation that is in the solutions package will not block until the wait group is done, which is the purpose of the exercise. However we can implement this also without using blocking mutex Lock() calls by using the TryLock() instead. Here is an example of one such implementation (disclaimer I haven't had much time to fully test this):
type WaitGrp struct {
groupSize int
cond *sync.Cond
mutex *sync.Mutex
}
func NewWaitGrp() *WaitGrp {
m := &sync.Mutex{}
return &WaitGrp{
cond: sync.NewCond(m),
mutex: m,
}
}
func (wg *WaitGrp) TryWait() bool {
result := false
if wg.mutex.TryLock() {
result = wg.groupSize == 0
wg.cond.L.Unlock()
}
return result
}