New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: sync.RWMutex: upgradable/downgradable locking #44049
Comments
Looks like a dup of #4026 . |
There have also been discussions about this on #4026, #23513, and #38891. And importantly note #4026 (comment): |
Ahhh looks like this has been suggested before, most recently in June, and @rsc declined based on no clear consensus. I'm fine closing this if that opinion prevails. Perhaps the |
I'm not sure I understand how this is supposed to work, could you explain more? It seems like "until the next waiting exclusive user returns its lock" will never occur. We are holding a read lock, so waiting writers can't ever unblock until we release the read lock, which never occurs. Is the intention that |
The idea for
Consider that in the context of the snippet: func connectToService(serviceName string) (*connectedService, error) {
// First check if we have a cached service.
cachedServicesMu.RLock()
for {
service, ok := cachedServices[serviceName]
if ok {
cachedServicesMu.RUnlock()
return service, nil
}
if cachedServicesMu.TryUpgradeToExclusive() { // <-- New API!
break
}
}
defer cachedServicesMu.Unlock()
// Not cached, so make the expensive connection.
service, err := doSomeConnectionDance(serviceName)
if err != nil {
return nil, err
}
// Cache it for later.
cachedServices[serviceName] = service
return service, nil
} We break out of that loop if we succeeded in getting the exclusive lock first. Otherwise we know somebody else got it first, but they're now done with it, so it's a good time for us to unblock and do another loop iteration with the read lock still held. |
What is wrong with this pattern (no loop, just unroll once)?:
|
Closing as a duplicate of #38891. |
No change in consensus, so declined. Edit: Oops, I need to fix the bot's handling of duplicate issues. Sorry for the confusing message! |
This issue is to gauge interest in adding
RWMutex.UpgradeToExcusive()
,RWMutex.TryUpgradeToExclusive()
, andRWMutex.DowngradeToRead()
.Consider this function:
This first checks a cache map using a read lock and then later upgrades it to a write lock. But there's a race during the upgrade, so it has to recheck mid-way through. Here's an improvement:
The
cachedServicesMu.TryUpgradeToExclusive()
line changes the lock from a read-lock to an exclusive-lock, without giving up the lock entirely in the middle. It blocks until it gets exclusive use, and returns true, or until the next waiting exclusive user returns its lock, in which case it returns false and doesn't upgrade.Is this functionality that's sufficiently interesting to others? Or is it too niche? Is it conceivably implementable using existing code or would it require changes that are too invasive?
CC @prattmic @CAFxX
The text was updated successfully, but these errors were encountered: