github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/lockskew/lockskew.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "flag" 9 "log" 10 "sync" 11 "time" 12 ) 13 14 var ( 15 doublelock = flag.Bool("2", false, "use two locks") 16 duration = flag.Duration("t", 100*time.Microsecond, "time to sleep") 17 ) 18 19 func main() { 20 flag.Parse() 21 22 done := make(chan bool) 23 var mu sync.Mutex 24 var mu2 sync.Mutex 25 go func() { 26 for { 27 select { 28 case <-done: 29 return 30 default: 31 if *doublelock { 32 mu2.Lock() 33 } 34 mu.Lock() 35 if *doublelock { 36 mu2.Unlock() 37 } 38 time.Sleep(*duration) 39 mu.Unlock() 40 } 41 } 42 }() 43 44 lastPrint := time.Now() 45 var sum time.Duration 46 for i := 0; ; i++ { 47 time.Sleep(*duration) 48 start := time.Now() 49 if *doublelock { 50 mu2.Lock() 51 } 52 mu.Lock() 53 if *doublelock { 54 mu2.Unlock() 55 } 56 now := time.Now() 57 mu.Unlock() 58 elapsed := now.Sub(start) 59 sum += elapsed 60 if i == 0 || now.Sub(lastPrint) > 1*time.Second { 61 log.Printf("lock#%d took %.6fs; average %.6fs\n", i, elapsed.Seconds(), (sum / time.Duration(i+1)).Seconds()) 62 lastPrint = now 63 } 64 } 65 }