Skip to content

go-lock is a lock library implementing read-write mutex and read-write trylock without starvation

License

Notifications You must be signed in to change notification settings

viney-shih/go-lock

Repository files navigation

go-lock

GoDev Build Status Go Report Card Codecov Coverage Status Sourcegraph License FOSSA Status Mentioned in Awesome Go

go-lock is a Golang library implementing an effcient read-write lock with the following built-in mechanism:

  • Mutex with timeout mechanism
  • Trylock
  • No-starve read-write solution

Native sync/Mutex and sync/RWMutex are very powerful and reliable. However, it became a disaster if the lock was not released as expected. Or, someone was holding the lock too long at the peak time leading whole system blocked. Dealing with those cases, go-lock implements TryLock, TryLockWithTimeout and TryLockWithContext function in addition to Lock and Unlock. It provides flexibility to control the resources.

Installation

go get github.com/viney-shih/go-lock

Example

package main

import (
	"fmt"
	"sync/atomic"
	"time"

	lock "github.com/viney-shih/go-lock"
)

func main() {
	// set RWMutex with CAS mechanism (CASMutex).
	var rwMut lock.RWMutex = lock.NewCASMutex()
	// set default value
	count := int32(0)

	// block here
	rwMut.Lock()
	go func() {
		time.Sleep(50 * time.Millisecond)
		fmt.Println("Now is", atomic.AddInt32(&count, 1)) // Now is 1
		rwMut.Unlock()
	}()

	// waiting for previous goroutine releasing the lock, and locking it again
	rwMut.Lock()
	fmt.Println("Now is", atomic.AddInt32(&count, 2)) // Now is 3

	// TryLock without blocking
	// Return false, because the lock is not released.
	fmt.Println("Return", rwMut.TryLock())

	// RTryLockWithTimeout without blocking
	// Return false, because the lock is not released.
	fmt.Println("Return", rwMut.RTryLockWithTimeout(50*time.Millisecond))

	// TryLockWithContext without blocking
	ctx, cancel := context.WithTimeout(context.TODO(), 50*time.Millisecond)
	defer cancel()
	// Return false, because the lock is not released.
	fmt.Println("Return", rwMut.TryLockWithContext(ctx))

	// release the lock in the end.
	rwMut.Unlock()

	// Output:
	// Now is 1
	// Now is 3
	// Return false
	// Return false
	// Return false
}

Benchmarks

  • Run on MacBook Pro (Retina, 15-inch, Mid 2015) 2.5 GHz Quad-Core Intel Core i7 16 GB 1600 MHz DDR3 using Go 1.15.2
  • Run with 1, 2, 4, 8 and 16 cpu to show it scales well...16 is double the # of logical cores on this machine.
go test -cpu=1,2,4,8,16 -bench=. -benchmem=true

goos: darwin
goarch: amd64
pkg: github.com/viney-shih/go-lock

(sync.RWMutex)
BenchmarkRWMutexLock                       	42591765	        27.4 ns/op	       0 B/op	       0 allocs/op
BenchmarkRWMutexLock-2                     	42713179	        27.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkRWMutexLock-4                     	44348323	        27.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkRWMutexLock-8                     	44135148	        27.9 ns/op	       0 B/op	       0 allocs/op
BenchmarkRWMutexLock-16                    	43566165	        27.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentRWMutexLock             	42971319	        27.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentRWMutexLock-2           	20131005	        57.5 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentRWMutexLock-4           	10752337	       115 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentRWMutexLock-8           	11434335	       105 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentRWMutexLock-16          	10495626	       109 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrent50RWMutexLock           	27979630	        42.8 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrent50RWMutexLock-2         	13037742	        86.6 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrent50RWMutexLock-4         	 9143397	       134 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrent50RWMutexLock-8         	 8335652	       139 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrent50RWMutexLock-16        	 7876855	       150 ns/op	       0 B/op	       0 allocs/op

(ChanMutex)
BenchmarkChanMutexLock                     	22619928	        51.8 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexLock-2                   	22769630	        51.6 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexLock-4                   	23096103	        51.7 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexLock-8                   	22627267	        51.1 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexLock-16                  	23092266	        51.7 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexLock           	23422556	        51.8 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexLock-2         	 6101949	       201 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexLock-4         	 5882083	       200 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexLock-8         	 5827183	       211 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexLock-16        	 5577098	       215 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexTryLock                  	22272500	        51.8 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexTryLock-2                	23004806	        52.2 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexTryLock-4                	22461870	        52.3 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexTryLock-8                	22901328	        53.8 ns/op	       0 B/op	       0 allocs/op
BenchmarkChanMutexTryLock-16               	22334739	        55.4 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexTryLock        	22112250	        53.9 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexTryLock-2      	13806072	        85.0 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexTryLock-4      	45892635	        32.6 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexTryLock-8      	396310569	         2.86 ns/op	       0 B/op	       0 allocs/op
BenchmarkConcurrentChanMutexTryLock-16     	512990590	         2.35 ns/op	       0 B/op	       0 allocs/op

(CASMutex)
BenchmarkCASMutexLock                      	 6160122	       186 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexLock-2                    	 7507022	       156 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexLock-4                    	 7646648	       156 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexLock-8                    	 7559616	       156 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexLock-16                   	 7576237	       158 ns/op	      96 B/op	       1 allocs/op
BenchmarkConcurrentCASMutexLock            	 6375879	       185 ns/op	      96 B/op	       1 allocs/op
BenchmarkConcurrentCASMutexLock-2          	 1690890	       706 ns/op	     251 B/op	       3 allocs/op
BenchmarkConcurrentCASMutexLock-4          	 1677104	       714 ns/op	     255 B/op	       3 allocs/op
BenchmarkConcurrentCASMutexLock-8          	 1808582	       639 ns/op	     255 B/op	       3 allocs/op
BenchmarkConcurrentCASMutexLock-16         	 1918422	       622 ns/op	     255 B/op	       3 allocs/op
BenchmarkConcurrent50CASMutexLock          	 5650274	       210 ns/op	      96 B/op	       1 allocs/op
BenchmarkConcurrent50CASMutexLock-2        	 1698381	       707 ns/op	     247 B/op	       3 allocs/op
BenchmarkConcurrent50CASMutexLock-4        	 1697070	       707 ns/op	     255 B/op	       3 allocs/op
BenchmarkConcurrent50CASMutexLock-8        	 1809859	       655 ns/op	     255 B/op	       3 allocs/op
BenchmarkConcurrent50CASMutexLock-16       	 1801652	       646 ns/op	     256 B/op	       4 allocs/op
BenchmarkCASMutexTryLock                   	 6593228	       182 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexTryLock-2                 	 7703084	       154 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexTryLock-4                 	 7790750	       151 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexTryLock-8                 	 7756263	       152 ns/op	      96 B/op	       1 allocs/op
BenchmarkCASMutexTryLock-16                	 7741186	       152 ns/op	      96 B/op	       1 allocs/op
BenchmarkConcurrentCASMutexTryLock         	 6509828	       189 ns/op	      96 B/op	       1 allocs/op
BenchmarkConcurrentCASMutexTryLock-2       	14058355	        82.2 ns/op	      17 B/op	       0 allocs/op
BenchmarkConcurrentCASMutexTryLock-4       	16875369	        71.4 ns/op	       8 B/op	       0 allocs/op
BenchmarkConcurrentCASMutexTryLock-8       	10985379	       109 ns/op	       4 B/op	       0 allocs/op
BenchmarkConcurrentCASMutexTryLock-16      	12405752	       104 ns/op	       1 B/op	       0 allocs/op
BenchmarkConcurrent50CASMutexTryLock       	 5631146	       204 ns/op	      96 B/op	       1 allocs/op
BenchmarkConcurrent50CASMutexTryLock-2     	 6518946	       182 ns/op	      61 B/op	       0 allocs/op
BenchmarkConcurrent50CASMutexTryLock-4     	 6937346	       174 ns/op	      43 B/op	       0 allocs/op
BenchmarkConcurrent50CASMutexTryLock-8     	 6493034	       182 ns/op	      39 B/op	       0 allocs/op
BenchmarkConcurrent50CASMutexTryLock-16    	 6177854	       202 ns/op	      41 B/op	       0 allocs/op
PASS

References

License

Apache-2.0

FOSSA Status