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  }