==
// Demonstrates record level locking. This's a simple mutex. A go-routine that succeeds the lock gets
// the mutex and thus can execute its part. It's then the responsibility of the very go-routine
// to unlock the mutext so that some other go-routine gets a chance to execute.
// Remember, locking is a blocking call and the go-routine that invokes the call to lock the mutex is blocked
// until its attempt of locking the mutex succeeds.
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var pCacheRecLock *sync.Mutex
func printMsg(goRoutineName, timeStamp, msg string) {
fmt.Printf("%s(%s): %s\n", goRoutineName, timeStamp, msg)
}
func f1(pWG *sync.WaitGroup) {
t := time.Now()
fmt.Printf("f1(%s): waiting for reclock...\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pCacheRecLock.Lock() // blocking call. go-routine is blocked untile it acquires the lock.
t = time.Now()
printMsg("f1", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond()),
"got reclock. am doing something great.")
pCacheRecLock.Unlock() // mutex is now available for other go-routines to acquire the same.
t = time.Now()
fmt.Printf("f1(%s): am done. reclock released.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pWG.Done()
}
func f2(pWG *sync.WaitGroup) {
t := time.Now()
fmt.Printf("f2(%s): waiting for reclock...\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pCacheRecLock.Lock() // blocking call. go-routine is blocked untile it acquires the lock.
t = time.Now()
printMsg("f2", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond()), "got reclock.")
pCacheRecLock.Unlock() // mutex is now available for other go-routines to acquire the same.
t = time.Now()
fmt.Printf("f2(%s): reclock released.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pWG.Done()
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) // allocates one logical processor for the scheduler to use
var wg sync.WaitGroup
wg.Add(2)
pCacheRecLock = &sync.Mutex{} // mutext is initialized.
go f1(&wg)
go f2(&wg)
t := time.Now()
fmt.Printf("main(%s): waiting for reclock...\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pCacheRecLock.Lock() // main() go-routine is also in contention. it's blocked until it acquires the lock.
t = time.Now()
printMsg("main", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond()), "got reclock.")
t = time.Now()
fmt.Printf("main(%s): reclock released.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pCacheRecLock.Unlock() // main() go-routine has done through its part. unlocking the mutext may enable other go-routines and one of the awating go-routines
// will be able to acquire the lock.
wg.Wait()
t = time.Now()
fmt.Printf("main(%s): exiting.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
}
==
In the 2nd example each go-routine executes a random sleep just to simulate the real life scenario.
==
// Demonstrates record level locking. This's a simple mutex. A go-routine that succeeds the lock gets
// the mutex and thus can execute its part. It's then the responsibility of the very go-routine
// to unlock the mutex so that some other go-routine gets a chance to execute.
// Remember, locking is a blocking call and the go-routine that invokes the call to lock the mutex is blocked
// until its attempt of locking the mutex succeeds.
//
// Introduces a random sleep in each go-routine just to simulate the real life scenario.
package main
import (
"fmt"
"runtime"
"sync"
"time"
"math/rand"
)
var pRecLock *sync.Mutex
func randomInt(min int, max int) int {
if min >= max {
return -1
}
return rand.Intn(max - min + 1) + min
}
func printMsg(goRoutineName, timeStamp, msg string) {
fmt.Printf("%s(%s): %s\n", goRoutineName, timeStamp, msg)
}
func f1(pWG *sync.WaitGroup) {
t := time.Now()
fmt.Printf("f1(%s): waiting for reclock...\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
time.Sleep(time.Duration(randomInt(1000, 3000)) * time.Millisecond) // random sleep.
pRecLock.Lock() // blocking call. go-routine is blocked untile it acquires the lock.
t = time.Now()
printMsg("f1", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond()),
"got reclock. am doing something great.")
time.Sleep(time.Duration(randomInt(1000, 3000)) * time.Millisecond) // random sleep.
pRecLock.Unlock() // mutex is now available for other go-routines to acquire the same.
t = time.Now()
fmt.Printf("f1(%s): am done. reclock released.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pWG.Done()
}
func f2(pWG *sync.WaitGroup) {
t := time.Now()
fmt.Printf("f2(%s): waiting for reclock...\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
time.Sleep(time.Duration(randomInt(1000, 3000)) * time.Millisecond) // random sleep.
pRecLock.Lock() // blocking call. go-routine is blocked untile it acquires the lock.
t = time.Now()
printMsg("f2", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond()), "got reclock.")
time.Sleep(time.Duration(randomInt(1000, 3000)) * time.Millisecond) // random sleep.
pRecLock.Unlock() // mutex is now available for other go-routines to acquire the same.
t = time.Now()
fmt.Printf("f2(%s): reclock released.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
pWG.Done()
}
func main() {
rand.Seed(time.Now().UnixNano()) // seeding to nano second granularity.
runtime.GOMAXPROCS(runtime.NumCPU()) // allocates one logical processor for the scheduler to use
var wg sync.WaitGroup
wg.Add(2)
pRecLock = &sync.Mutex{} // mutext is initialized.
go f1(&wg)
go f2(&wg)
t := time.Now()
fmt.Printf("main(%s): waiting for reclock...\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
time.Sleep(time.Duration(randomInt(1000, 3000)) * time.Millisecond) // main() go-routine also introduces a random sleep.
pRecLock.Lock() // main() go-routine is also in contention. it's blocked until it acquires the lock.
t = time.Now()
printMsg("main", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond()), "got reclock.")
time.Sleep(time.Duration(randomInt(1000, 3000)) * time.Millisecond) // random sleep.
pRecLock.Unlock() // main() go-routine has done through its part. unlocking the mutext may enable other go-routines and one of the awating go-routines
// will be able to acquire the lock.
t = time.Now()
fmt.Printf("main(%s): reclock released.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
wg.Wait()
t = time.Now()
fmt.Printf("main(%s): exiting.\n", fmt.Sprintf("%02d-%02d-%d:%02d-%02d-%02d-%06d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute(),
t.Second(), t.Nanosecond()))
}
==