TryLock support on read-write lock for Golang

go-trylock

GoDoc Build Status Coverage Status Go Report Card License

TryLock support on read-write lock for Golang

Interface

go-trylock implements sync.Locker.

Have same interfaces with sync.RWMutex

Documentation can be found at Godoc

Examples

import (
    "context"
    "time"
    "errors"
    "github.com/subchen/go-trylock/v2"
)

var mu = trylock.New()

func goroutineWrite() error {
    if ok := mu.TryLock(context.Background()); !ok {
    	return errors.New("timeout, cannot TryLock !!!")
    }
    defer mu.Unlock()
    
    // write something
}

func goroutineWriteTimeout() error {
    if ok := mu.TryLockTimeout(1 * time.Second); !ok {
    	return errors.New("timeout, cannot TryLock !!!")
    }
    defer mu.Unlock()
    
    // write something
}

func goroutineRead() {
    if ok := mu.RTryLock(context.Background()); !ok {
    	return errors.New("timeout, cannot RTryLock !!!")
    }
    defer mu.RUnlock()
    
    // read something
}

func goroutineReadTimeout() {
    if ok := mu.RTryLockTimeout(1 * time.Second); !ok {
    	return errors.New("timeout, cannot RTryLock !!!")
    }
    defer mu.RUnlock()
    
    // read something
}

LICENSE

Apache 2.0

Similar Resources

Routine - ThreadLocal for golang

routine 中文版 routine encapsulates and provides some easy-to-use, high-performance

Jan 1, 2023

Golang Implementation of Worker Pool/ Thread Pool

Golang Implementation of Worker Pool/ Thread Pool

Jun 18, 2022

Goworkers - Zero dependency Golang worker pool

Golang Worker Pool Zero dependency golang goroutines pool library. It is useful

Apr 28, 2022

Go-miningcore-pool - Miningcore Pool written in GOlang

Go-Miningcore-Pool (COMING SOON) Miningcore Pool written in GOlang 0x01 Configur

Apr 24, 2022

Worker - A Golang library that provides worker pools

Worker A Golang library that provides worker pools. Usage See *_test.go files. T

Apr 15, 2022

Go-redisson: A redisson like distributed redis lock, support watchdog、reentrant lock

go-redisson a Redisson like distributed locking implementation using Redis. Installation go get github.com/cheerego/go-redisson Lock Category Mutex Ex

Dec 17, 2022

solution lock for golang, locallock and remote lock base on redis.

solution lock for golang, locallock and remote lock base on redis.

Dec 19, 2022

Write controller-runtime based k8s controllers that read/write to git, not k8s

Git Backed Controller The basic idea is to write a k8s controller that runs against git and not k8s apiserver. So the controller is reading and writin

Dec 10, 2021

A Golang lock-free thread-safe HashMap optimized for fastest read access.

hashmap Overview A Golang lock-free thread-safe HashMap optimized for fastest read access. Usage Set a value for a key in the map: m := &HashMap{} m.S

Dec 30, 2022

Time Series Database based on Cassandra with Prometheus remote read/write support

SquirrelDB SquirrelDB is a scalable high-available timeseries database (TSDB) compatible with Prometheus remote storage. SquirrelDB store data in Cass

Oct 20, 2022

A db proxy for distributed transaction, read write splitting and sharding! Support any language! It can be deployed as a sidecar in a pod.

A db proxy for distributed transaction, read write splitting and sharding! Support any language! It can be deployed as a sidecar in a pod.

DBPack DBPack means a database cluster tool pack. It can be deployed as a sidecar in a pod, it shields complex basic logic, so that business developme

Dec 29, 2022

Lockgate is a cross-platform locking library for Go with distributed locks using Kubernetes or lockgate HTTP lock server as well as the OS file locks support.

Lockgate Lockgate is a locking library for Go. Classical interface: 2 types of locks: shared and exclusive; 2 modes of locking: blocking and non-block

Dec 16, 2022

golang library to read and write various subtitle formats

libgosubs Golang library to read and write subtitles in the following formats Advanced SubStation Alpha v4 SRT TTML v1.0 - This is based on the spec p

Sep 27, 2022

Golang bot that connects to slack using Socketclient to read and write messages.

Golang bot that connects to slack using Socketclient to read and write messages.

🚀 (not)simple go project 🚀 Golang bot that connects to slack using Socketclient to read and write messages. 🏆 Use 🏆 @SquidBot : Mentions your name

Aug 23, 2022

Simple-read-file - Example of how to read file in Go

simple-read-file This repository contains a simple example of how to read file i

Jan 11, 2022

Litestream-read-replica-demo - A demo application for running live read replication on fly.io with Litestream

Litestream Read Replica Demo A demo application for running live read replicatio

Oct 18, 2022

Package ini provides INI file read and write functionality in Go.

INI Package ini provides INI file read and write functionality in Go. Features Load from multiple data sources(file, []byte, io.Reader and io.ReadClos

Dec 29, 2022

🔑A high performance Key/Value store written in Go with a predictable read/write performance and high throughput. Uses a Bitcask on-disk layout (LSM+WAL) similar to Riak.

bitcask A high performance Key/Value store written in Go with a predictable read/write performance and high throughput. Uses a Bitcask on-disk layout

Sep 26, 2022

Database wrapper that manage read write connections

rwdb Database wrapper that manage read write connections Install go get github.com/andizzle/rwdb Create connections package main import "github.com/

Dec 10, 2022
Comments
  • add some benchmarks. concurrency test case was failed.

    add some benchmarks. concurrency test case was failed.

    I run go test -bench=. many times, then I got some deadlock in concurrency test cases.

    Lock

    goos: linux
    goarch: amd64
    pkg: github.com/subchen/go-trylock/v2
    BenchmarkStdLock/goroutine-1-8         	129828927	         9.04 ns/op	       0 B/op	       0 allocs/op
    BenchmarkStdLock/goroutine-N-8         	 4820733	       248 ns/op	       0 B/op	       0 allocs/op
    BenchmarkLock/goroutine-1-8            	15406830	        83.9 ns/op	      96 B/op	       1 allocs/op
    BenchmarkLock/goroutine-N-8            	fatal error: all goroutines are asleep - deadlock!
    
    goroutine 1 [chan receive]:
    testing.(*B).run1(0xc000126380, 0xc000126380)
    	/usr/lib/go/src/testing/benchmark.go:233 +0x9e
    testing.(*B).Run(0xc000126000, 0x54a08e, 0xd, 0x5525d8, 0x4bb900)
    	/usr/lib/go/src/testing/benchmark.go:651 +0x341
    testing.runBenchmarks.func1(0xc000126000)
    	/usr/lib/go/src/testing/benchmark.go:533 +0x78
    testing.(*B).runN(0xc000126000, 0x1)
    	/usr/lib/go/src/testing/benchmark.go:191 +0xe8
    testing.runBenchmarks(0x54e716, 0x20, 0xc00000c120, 0x6454c0, 0x4, 0x4, 0xc000072e01)
    	/usr/lib/go/src/testing/benchmark.go:539 +0x390
    testing.(*M).Run(0xc000110000, 0x0)
    	/usr/lib/go/src/testing/testing.go:1205 +0x42d
    main.main()
    	_testmain.go:70 +0x135
    
    goroutine 5830919 [chan receive]:
    testing.(*B).doBench(0xc000126540, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/usr/lib/go/src/testing/benchmark.go:277 +0x73
    testing.(*benchContext).processBench(0xc00000c140, 0xc000126540)
    	/usr/lib/go/src/testing/benchmark.go:568 +0x207
    testing.(*B).run(0xc000126540)
    	/usr/lib/go/src/testing/benchmark.go:268 +0x63
    testing.(*B).Run(0xc000126380, 0x549b96, 0xb, 0xc00000c0a0, 0x4bb900)
    	/usr/lib/go/src/testing/benchmark.go:652 +0x3fd
    github.com/subchen/go-trylock/v2.BenchmarkLock(0xc000126380)
    	/home/cupen/workbench/repos/go-trylock/benchmarks_test.go:46 +0x166
    testing.(*B).runN(0xc000126380, 0x1)
    	/usr/lib/go/src/testing/benchmark.go:191 +0xe8
    testing.(*B).run1.func1(0xc000126380)
    	/usr/lib/go/src/testing/benchmark.go:231 +0x57
    created by testing.(*B).run1
    	/usr/lib/go/src/testing/benchmark.go:224 +0x7d
    
    goroutine 5501051 [semacquire]:
    sync.runtime_Semacquire(0xc000184038)
    	/usr/lib/go/src/runtime/sema.go:56 +0x42
    sync.(*WaitGroup).Wait(0xc000184030)
    	/usr/lib/go/src/sync/waitgroup.go:130 +0x64
    github.com/subchen/go-trylock/v2.BenchmarkLock.func2(0xc000126540)
    	/home/cupen/workbench/repos/go-trylock/benchmarks_test.go:59 +0x109
    testing.(*B).runN(0xc000126540, 0x488d36)
    	/usr/lib/go/src/testing/benchmark.go:191 +0xe8
    testing.(*B).launch(0xc000126540)
    	/usr/lib/go/src/testing/benchmark.go:321 +0xea
    created by testing.(*B).doBench
    	/usr/lib/go/src/testing/benchmark.go:276 +0x55
    
    goroutine 11595769 [select]:
    github.com/subchen/go-trylock/v2.(*trylocker).TryLock(0xc00000c020, 0x574380, 0xc00001a108, 0x552918)
    	/home/cupen/workbench/repos/go-trylock/trylock.go:91 +0x111
    github.com/subchen/go-trylock/v2.(*trylocker).Lock(0xc00000c020)
    	/home/cupen/workbench/repos/go-trylock/trylock.go:135 +0x43
    github.com/subchen/go-trylock/v2.BenchmarkLock.func2.1(0x575020, 0xc00000c020, 0xc000184020, 0xc000184030)
    	/home/cupen/workbench/repos/go-trylock/benchmarks_test.go:53 +0x31
    created by github.com/subchen/go-trylock/v2.BenchmarkLock.func2
    	/home/cupen/workbench/repos/go-trylock/benchmarks_test.go:52 +0xe1
    exit status 2
    FAIL	github.com/subchen/go-trylock/v2	10.836s
    

    TryLock

    goos: linux
    goarch: amd64
    pkg: github.com/subchen/go-trylock/v2
    BenchmarkStdLock/goroutine-1-8         	129199300	         9.01 ns/op	       0 B/op	       0 allocs/op
    BenchmarkStdLock/goroutine-N-8         	 5359784	       224 ns/op	       0 B/op	       0 allocs/op
    BenchmarkLock/goroutine-1-8            	15884559	        94.5 ns/op	      96 B/op	       1 allocs/op
    BenchmarkLock/goroutine-N-8            	 4319998	       269 ns/op	      98 B/op	       1 allocs/op
    BenchmarkTryLock/goroutine-1-8         	14686035	        89.6 ns/op	      96 B/op	       1 allocs/op
    BenchmarkTryLock/goroutine-N-8         	fatal error: all goroutines are asleep - deadlock!
    
    goroutine 1 [chan receive]:
    testing.(*B).run1(0xc0001ae1c0, 0xc0001ae1c0)
    	/usr/lib/go/src/testing/benchmark.go:233 +0x9e
    testing.(*B).Run(0xc0001ae000, 0x54a93a, 0x10, 0x552608, 0x4bb900)
    	/usr/lib/go/src/testing/benchmark.go:651 +0x341
    testing.runBenchmarks.func1(0xc0001ae000)
    	/usr/lib/go/src/testing/benchmark.go:533 +0x78
    testing.(*B).runN(0xc0001ae000, 0x1)
    	/usr/lib/go/src/testing/benchmark.go:191 +0xe8
    testing.runBenchmarks(0x54e716, 0x20, 0xc00018c0a0, 0x6454c0, 0x4, 0x4, 0xc000072e01)
    	/usr/lib/go/src/testing/benchmark.go:539 +0x390
    testing.(*M).Run(0xc000090000, 0x0)
    	/usr/lib/go/src/testing/testing.go:1205 +0x42d
    main.main()
    	_testmain.go:70 +0x135
    
    goroutine 11178443 [chan receive]:
    testing.(*B).doBench(0xc0001ae540, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    	/usr/lib/go/src/testing/benchmark.go:277 +0x73
    testing.(*benchContext).processBench(0xc00018c0c0, 0xc0001ae540)
    	/usr/lib/go/src/testing/benchmark.go:568 +0x207
    testing.(*B).run(0xc0001ae540)
    	/usr/lib/go/src/testing/benchmark.go:268 +0x63
    testing.(*B).Run(0xc0001ae1c0, 0x549b96, 0xb, 0xc00000c0a0, 0x4bb900)
    	/usr/lib/go/src/testing/benchmark.go:652 +0x3fd
    github.com/subchen/go-trylock/v2.BenchmarkTryLock(0xc0001ae1c0)
    	/home/cupen/workbench/repos/go-trylock/benchmarks_test.go:78 +0x166
    testing.(*B).runN(0xc0001ae1c0, 0x1)
    	/usr/lib/go/src/testing/benchmark.go:191 +0xe8
    testing.(*B).run1.func1(0xc0001ae1c0)
    	/usr/lib/go/src/testing/benchmark.go:231 +0x57
    created by testing.(*B).run1
    	/usr/lib/go/src/testing/benchmark.go:224 +0x7d
    
    goroutine 11700080 [semacquire]:
    sync.runtime_Semacquire(0xc00001a198)
    	/usr/lib/go/src/runtime/sema.go:56 +0x42
    sync.(*WaitGroup).Wait(0xc00001a190)
    	/usr/lib/go/src/sync/waitgroup.go:130 +0x64
    github.com/subchen/go-trylock/v2.BenchmarkTryLock.func2(0xc0001ae540)
    	/home/cupen/workbench/repos/go-trylock/benchmarks_test.go:93 +0x11a
    testing.(*B).runN(0xc0001ae540, 0x64)
    	/usr/lib/go/src/testing/benchmark.go:191 +0xe8
    testing.(*B).launch(0xc0001ae540)
    	/usr/lib/go/src/testing/benchmark.go:321 +0xea
    created by testing.(*B).doBench
    	/usr/lib/go/src/testing/benchmark.go:276 +0x55
    exit status 2
    FAIL	github.com/subchen/go-trylock/v2	9.281s
    
  • Feature request

    Feature request

    Add an interface for using a context.Context.Done() channel instead of a fixed timeout. This would allow greater flexibility for canceling a TryLock call.

  • checking state first in Unlock / RUnlock?

    checking state first in Unlock / RUnlock?

    https://github.com/subchen/go-trylock/blob/6894780a9a5161a47127990acaebf7d2d8fc4fd5/trylock.go#L156

    atomic.LoadInt32, and then check state then panic , or there's no way back to reset state in recover

  • seems like there's possible rlock blocking issue

    seems like there's possible rlock blocking issue

    https://github.com/subchen/go-trylock/blob/6894780a9a5161a47127990acaebf7d2d8fc4fd5/trylock.go#L120

    func (m *trylocker) RTryLock(ctx context.Context) bool {
    	for {
    		n := atomic.LoadInt32(m.state)
    		if n >= 0 {
    			if atomic.CompareAndSwapInt32(m.state, n, n+1) {
    				// acquire OK
    				return true
    			}
    		}
    		if ctx == nil {
    			return false
    		}
    
    		// get broadcast channel
    		ch := m.channel()
    
    		select {
    		case <-ch:
    			// wake up to try again
    		case <-ctx.Done():
    			// timeout
    			return false
    		}
    	}
    }
    

    say there are two goroutines, W using Lock and R using RLock

    t0: R: failed to CompareAndSwapInt32 (going to get ch and wait signal) t1: W: swap chan t2: R: get a new chan (need try to CompareAndSwapInt32 again in fact) t3: W: close old chan (no signal sent to the new chan) now: R blocking

Simple in-memory job queue for Golang using worker-based dispatching

artifex Simple in-memory job queue for Golang using worker-based dispatching Documentation here: https://godoc.org/github.com/mborders/artifex Cron jo

Dec 24, 2022
CyclicBarrier golang implementation

cyclicbarrier CyclicBarrier is a synchronizer that allows a set of goroutines to wait for each other to reach a common execution point, also called a

Nov 30, 2022
golang worker pool , Concurrency limiting goroutine pool

golang worker pool 中文说明 Concurrency limiting goroutine pool. Limits the concurrency of task execution, not the number of tasks queued. Never blocks su

Dec 19, 2022
Fast resizable golang semaphore primitive

semaphore Fast resizable golang semaphore based on CAS allows weighted acquire/release; supports cancellation via context; allows change semaphore lim

Dec 13, 2022
Golang simple thread pool implementation

Golang Threadpool implementation Scalable threadpool implementation using Go to handle the huge network trafic. Install go get github.com/shettyh/thre

Dec 12, 2022
Off heap golang memory pool

Stealthpool stealthpool provides a memory pool that allocates blocks off-heap that will NOT be tracked by the garbage collector. The name stealthpool

Dec 5, 2022
Queue is a Golang library for spawning and managing a Goroutine pool

Queue is a Golang library for spawning and managing a Goroutine pool, Alloowing you to create multiple worker according to limit CPU number of machine.

Jan 9, 2023
Queue is a Golang library for spawning and managing a Goroutine pool

Queue is a Golang library for spawning and managing a Goroutine pool, Alloowing you to create multiple worker according to limit CPU number of machine.

Jan 2, 2023
This repository collects common concurrency patterns in Golang

Go Concurrency Patterns This repository collects common concurrency patterns in Golang Materials Concurrency is not parallelism Go Concurrency Pattern

Jan 9, 2023
goroutine pool in golang

goroutine pool in golang

Nov 1, 2021