Memory Lock

The memory lock module, also known as the dynamic mutex lock module, supports dynamically generating mutex locks based on given key names, ensuring concurrency safety and supporting the Try*Lock feature.

In scenarios where a large number of dynamic mutex locks are maintained, please manually call the Remove method to delete mutex lock objects that are no longer in use.

Usage :

import "github.com/gogf/gf/v2/os/gmlock"

Usage scenarios : Scenarios that require dynamic creation of mutex locks, or need to maintain a large number of dynamic locks;

Interface documentation :

https://pkg.go.dev/github.com/gogf/gf/v2/os/gmlock

func Lock(key string)
func LockFunc(key string, f func())
func RLock(key string)
func RLockFunc(key string, f func())
func RUnlock(key string)
func Remove(key string)
func TryLock(key string) bool
func TryLockFunc(key string, f func()) bool
func TryRLock(key string) bool
func TryRLockFunc(key string, f func()) bool
func Unlock(key string)
type Locker
    func New() *Locker
    func (l *Locker) Clear()
    func (l *Locker) Lock(key string)
    func (l *Locker) LockFunc(key string, f func())
    func (l *Locker) RLock(key string)
    func (l *Locker) RLockFunc(key string, f func())
    func (l *Locker) RUnlock(key string)
    func (l *Locker) Remove(key string)
    func (l *Locker) TryLock(key string) bool
    func (l *Locker) TryLockFunc(key string, f func()) bool
    func (l *Locker) TryRLock(key string) bool
    func (l *Locker) TryRLockFunc(key string, f func()) bool
    func (l *Locker) Unlock(key string)

Example 1: Basic Usage

package main

import (
    "time"
    "sync"
    "github.com/gogf/gf/v2/os/glog"
    "github.com/gogf/gf/v2/os/gmlock"
)

func main() {
    key := "lock"
    wg  := sync.WaitGroup{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            gmlock.Lock(key)
            glog.Println(i)
            time.Sleep(time.Second)
            gmlock.Unlock(key)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

In this example, it simulates opening 10 goroutines simultaneously, but at any one time only one goroutine can acquire the lock. The goroutine with the lock will execute for 1 second before exiting, allowing other goroutines to acquire the lock.

After execution, the output is:

2018-10-15 23:57:28.295 9
2018-10-15 23:57:29.296 0
2018-10-15 23:57:30.296 1
2018-10-15 23:57:31.296 2
2018-10-15 23:57:32.296 3
2018-10-15 23:57:33.297 4
2018-10-15 23:57:34.297 5
2018-10-15 23:57:35.297 6
2018-10-15 23:57:36.298 7
2018-10-15 23:57:37.298 8

Example 2: TryLock Non-blocking Lock

The TryLock method returns a value, indicating whether the lock was successfully acquired. If successful, it returns true; if the lock is already acquired by another goroutine, it returns false.

package main

import (
    "sync"
    "github.com/gogf/gf/v2/os/glog"
    "time"
    "github.com/gogf/gf/v2/os/gmlock"
)

func main() {
    key := "lock"
    wg  := sync.WaitGroup{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            if gmlock.TryLock(key) {
                glog.Println(i)
                time.Sleep(time.Second)
                gmlock.Unlock(key)
            } else {
                glog.Println(false)
            }
            wg.Done()
        }(i)
    }
    wg.Wait()
}

Similarly, in this example, only 1 goroutine can acquire the lock at the same time, and other goroutines will exit immediately if TryLock fails.

After execution, the output is:

2018-10-16 00:01:59.172 9
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.172 false
2018-10-16 00:01:59.176 false