multilock

package module
v0.0.0-...-31d195f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2017 License: Apache-2.0 Imports: 2 Imported by: 1

README

Multilock

Build Status

Multilock allows you to obtain multiple locks without deadlock. It also uses strings as locks, which allows multiple goroutines to synchronize independently without having to share common mutex objects.

One common application is to use external ids (e.g. resource ids, filenames, database ids) as the lock, and thereby preventing multiple goroutines from potentially reading/writing to the same resources, creating some form of transactional locking.

Installation
go get github.com/atedja/go-multilock
Example
package main

import (
  "fmt"
  "sync"
  "github.com/atedja/go-multilock"
)

func main() {
  var wg sync.WaitGroup
  wg.Add(2)

  john := 1000
  susan := 2000

  go func() {
    lock := multilock.New("john", "susan")
    lock.Lock()
    defer lock.Unlock()

    fmt.Println("Transferring money from john to susan")
    john -= 200
    susan += 200
    wg.Done()
  }()

  go func() {
    lock := multilock.New("susan", "john")
    lock.Lock()
    defer lock.Unlock()

    fmt.Println("Transferring money from susan to john")
    john += 400
    susan -= 400
    wg.Done()
  }()

  fmt.Println("john's balance", john)
  fmt.Println("susan's balance", susan)

  wg.Wait()
}
Full API Documentation
Basic Usage
Lock and Unlock
lock := multilock.New("somekey")
lock.Lock()
defer lock.Unlock()
Yield

Temporarily unlocks the acquired lock, yields cpu time to other goroutines, then attempts to lock the same keys again.

lock := multilock.New("somekey")
lock.Lock()
for resource["somekey"] == nil {
  lock.Yield()
}
// process resource["somekey"]
Unlock(lock)
Clean your unused locks

If you use nondeterministic number of keys, e.g. timestamp, then overtime the number of locks will grow creating a memory "leak". Clean() will remove unused locks. This method is threadsafe, and can be executed even while other goroutines furiously attempt to acquire other keys. If some keys are to be used again, Multilock will automatically create new locks for those keys and everybody is happy again.

multilock.Clean()
Compatibility with sync.Locker interface

multilock.Lock implements sync.Locker interface, and can be used by other locking mechanism, e.g. sync.Cond.

Best Practices
Specify all your locks at once

Specify all the locks you need for your transaction at once. DO NOT create nested Lock() statements. The lock is not reentrant. Likewise, you should not call Unlock() without a matching Lock(). They are both blocking.

Always Unlock your locks

Just common sense.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Clean

func Clean() []string

Cleans old unused locks. Returns removed keys.

Types

type Lock

type Lock struct {
	// contains filtered or unexported fields
}

func New

func New(locks ...string) *Lock

Creates a new multilock for the specified keys

func (*Lock) Lock

func (self *Lock) Lock()

func (*Lock) Unlock

func (self *Lock) Unlock()

Unlocks this lock. Must be called after Lock. Can only be invoked if there is a previous call to Lock.

func (*Lock) Yield

func (self *Lock) Yield()

Temporarily unlocks, gives up the cpu time to other goroutine, and attempts to lock again.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL