怎么实现tryLock(timeout int)的功能

这是我自己尝试写的一个

package internal_struct

import (
    "sync/atomic"
    "time"
)

type MutexLock struct {
    i *int32
}

func NewMutexLock() *MutexLock {
    var i int32
    i = 0
    return &MutexLock{&i}
}

func (m *MutexLock) TryLock(timeout int) bool {
    t := timeout
    b := false
    for !b {
        b = atomic.CompareAndSwapInt32(m.i, 0, 1)
        if b {
            break
        }
        t--
        if t == 0 {
            break
        }
        time.Sleep(time.Millisecond)
    }
    return b
}

func (m *MutexLock) UnLock() {
    atomic.CompareAndSwapInt32(m.i, 1, 0)
}

测试代码

package internal_struct

import (
    "sync/atomic"
    "testing"
    "time"
)

func TestMutexLock_TryLock(t *testing.T) {
    mutex := NewMutexLock()
    t.Log(mutex.TryLock(1))
    t.Log(mutex.TryLock(1))
    mutex.UnLock()
    t.Log(mutex.TryLock(1))
}

func TestMutexLock_UnLock(t *testing.T) {
    mutex := NewMutexLock()
    t.Log(mutex.TryLock(1))
    mutex.UnLock()
    t.Log(mutex.TryLock(1))
}

func TestMutexLock_TryLock2(t *testing.T) {
    mutex := NewMutexLock()
    var tid int32 = 0
    i := 0
    for ; i <= 20; i++ {

        go func() {
            id := atomic.AddInt32(&tid, 1)
            f := mutex.TryLock(20)

            t.Log(id, "【", time.Now(), "】", "-->", f)
            time.Sleep(500*time.Millisecond)
            if f {
                t.Log(id, "【", time.Now(), "】", "-->unlock")
                mutex.UnLock()
            }
        }()

        time.Sleep(time.Millisecond * 50)
    }

    time.Sleep(10 * time.Second)
}
已邀请:

stevewang

赞同来自: xiayf bigpyer

可以利用channel来实现,效率会比sync.Mutex差一些。

import (
    "errors"
    "fmt"
    "time"
)

type Lock struct {
    ch chan struct{}
}

func NewLock() *Lock {
    return &Lock{
        ch: make(chan struct{}, 1),
    }
}

func (l *Lock) Lock() {
    l.ch <- struct{}{}
}

func (l *Lock) Unlock() {
    <-l.ch
}

func (l *Lock) TryLock(timeout time.Duration) error {
    t := time.After(timeout)
    select {
    case l.ch <- struct{}{}:
        return nil
    case <-t:
        return errors.New("timeout")
    }
}

stevewang

赞同来自:

这个函数是什么功能? timeout参数是做什么用的?单位是什么?

xiayf - 程序员,译者,GO、Python、PHP、JS

赞同来自:

尝试加锁,超时则返回失败?

su21

赞同来自:

用 channel 实现。

ch := make(chan struct{}, 1)
func tryLock() {
    select {
        case ch <- struct{}{}: return true
        case <-timeAfter(timeout): return false
    }
}
func unlock() {
    <-ch
}

dongzerun

赞同来自:

可以 test 测一下,性能应该会差很多,不同并发数下得好好测下

要回复问题请先登录注册