-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
sync: document that double RLock isn't safe #15418
Comments
I found a simpler case looks like this issues. http://play.golang.org/p/pEhnPbsnDG package main
import (
"sync"
"time"
)
func main() {
/*
TimeLine:
* Thread A locker.RLock() return
* Thread B locker.Lock() start
* Thread A locker.RLock() start
* Thread A and Thread B are deadlock
*/
locker:=sync.RWMutex{}
locker.RLock()
go func(){
locker.Lock()
locker.Unlock()
}()
time.Sleep(10*time.Millisecond)
locker.RLock()
locker.RUnlock()
locker.RUnlock()
time.Sleep(10*time.Millisecond)
} I found another case which is not deadlock. package main
import (
"sync"
"time"
)
func main() {
locker:=sync.RWMutex{}
locker.RLock()
go func(){
locker.Lock()
locker.Unlock()
}()
go func(){
time.Sleep(10*time.Millisecond)
locker.RLock()
locker.RUnlock()
}()
time.Sleep(20*time.Millisecond)
locker.RUnlock()
} So It looks like that you should not use RLock twice in the same thread from those examples. |
Yes, it's not safe to recursively acquire an RLock. It is documented a bit already, indirectly:
|
@bradfitz
|
@bronze1man the goroutine doesn't matter. Any RLock caller cannot depend on a future RLock succeeding in any goroutine as long as the first RLock is held. |
That's a pretty significant limitation given the reason to use an The docs currently say:
Clearly current behaviour does conform to the above (unless you read the bit in bold as 'the lock might be able to be held by an arbitrary number of readers' which I would suggest is an unnatural interpretation). At the least this is a documentation problem, but given the fact that |
IMO, the docs are correct. Any numbers of goroutines may simultaneously acquire a It's a general principle, applicable to all mutexes provided by the stdlib. The same goroutine cannot lock any mutex if it already did that and did not yet unlocked it. |
@cznic according to @bradfitz , the goroutine does not matter:
(my emphasis) What he is saying (I think) is that if goroutine A takes an RLock, it cannot rely on goroutine B being able to acquire an RLock() before A drops its RLock. |
@abligh I know the goroutine does not matter. I think @bradfitz says that you can not have one thread call RLock twice and call RUnlock twice in sequence,and have an other thread call Lock at the same time.It will deadlock with little possibility.(It just look like the possibility of the data race has happend.) By the way,I think using the case in the way that i have found is better than the sentence "Any RLock caller cannot depend on a future RLock succeeding in any goroutine as long as the first RLock is held". |
I've seen so much confusion about this in the past few months that I've promoted this to a Go1.7 documentation issue, instead of a "Maybe". I do think it needs to be documented well. I know we generally tell people to stay out of the sync package (or atomic package too) if they don't know what they're doing, but people still use these things, so warnings should be on the label. @dvyukov, can you maybe write some docs here? |
How about this?
I would put such important notes on the type rather than on methods. |
CL https://golang.org/cl/23570 mentions this issue. |
Please answer these questions before submitting your issue. Thanks!
go version
)?go version go1.6 darwin/amd64
go env
)?GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH=""
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GO15VENDOREXPERIMENT="1"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"
http://play.golang.org/p/UWIAmPCRCu
output 4000
fatal error: all goroutines are asleep - deadlock!
runNum more big,the probability of deadlock more often
The text was updated successfully, but these errors were encountered: