Add critical section to protect lim.limit

Among 9 usages of lim.limit , 8 of them are protected by ``, but the one at line 226 is not protected. So I add a critical section to protect the read operation.

Among 8 usages of lim.limit that are protected, there are 2 usages at line 350 and 357 in function `lim.advance()`. They may seem to be unprotected at first glance, since `` doesn't appear in `lim.advance()`, but actually all three usages of `lim.advance()` are in critical section.

***How to trigger this bug***
I found this bug occasionally by my static checker, so I can only come up with a hypothesis to trigger it:

If one goroutine is calling `rate.WaitN()` and another goroutine is calling `rate.SetLimitAt()`, then the read operation in `rate.WaitN()` and the write operation in `rate.SetLimitAt()` will race.

***About my patch***
There are several ways to fix this bug, and I chose an efficient but not elegant one. Please let me know if you think other ways are better.

Change-Id: I229bc06a2caa483b9dfb0f4e682cfc144c5aa07c
GitHub-Last-Rev: 192792cf2c5d0d3e8d1ac1345ead38f6ab3c46bc
GitHub-Pull-Request: golang/time#7
Reviewed-by: Sameer Ajmani <>
diff --git a/rate/rate.go b/rate/rate.go
index 3cd1498..563f704 100644
--- a/rate/rate.go
+++ b/rate/rate.go
@@ -223,7 +223,12 @@
 // canceled, or the expected wait time exceeds the Context's Deadline.
 // The burst limit is ignored if the rate limit is Inf.
 func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) {
-	if n > lim.burst && lim.limit != Inf {
+	burst := lim.burst
+	limit := lim.limit
+	if n > burst && limit != Inf {
 		return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst)
 	// Check if ctx is already cancelled