// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. // // This Source Code Form is subject to the terms of the MIT License. // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. package gmlock_test import ( "sync" "testing" "time" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/os/gmlock" "github.com/gogf/gf/test/gtest" ) func Test_Locker_Lock(t *testing.T) { gtest.C(t, func(t *gtest.T) { key := "testLock" array := garray.New(true) go func() { gmlock.Lock(key) array.Append(1) time.Sleep(300 * time.Millisecond) gmlock.Unlock(key) }() go func() { time.Sleep(100 * time.Millisecond) gmlock.Lock(key) array.Append(1) gmlock.Unlock(key) }() time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(200 * time.Millisecond) t.Assert(array.Len(), 2) gmlock.Remove(key) }) gtest.C(t, func(t *gtest.T) { key := "testLock" array := garray.New(true) lock := gmlock.New() go func() { lock.Lock(key) array.Append(1) time.Sleep(300 * time.Millisecond) lock.Unlock(key) }() go func() { time.Sleep(100 * time.Millisecond) lock.Lock(key) array.Append(1) lock.Unlock(key) }() time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(200 * time.Millisecond) t.Assert(array.Len(), 2) lock.Clear() }) } func Test_Locker_TryLock(t *testing.T) { gtest.C(t, func(t *gtest.T) { key := "testTryLock" array := garray.New(true) go func() { gmlock.Lock(key) array.Append(1) time.Sleep(300 * time.Millisecond) gmlock.Unlock(key) }() go func() { time.Sleep(150 * time.Millisecond) if gmlock.TryLock(key) { array.Append(1) gmlock.Unlock(key) } }() go func() { time.Sleep(400 * time.Millisecond) if gmlock.TryLock(key) { array.Append(1) gmlock.Unlock(key) } }() time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(300 * time.Millisecond) t.Assert(array.Len(), 2) }) } func Test_Locker_LockFunc(t *testing.T) { //no expire gtest.C(t, func(t *gtest.T) { key := "testLockFunc" array := garray.New(true) go func() { gmlock.LockFunc(key, func() { array.Append(1) time.Sleep(300 * time.Millisecond) }) // }() go func() { time.Sleep(100 * time.Millisecond) gmlock.LockFunc(key, func() { array.Append(1) }) }() time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(100 * time.Millisecond) t.Assert(array.Len(), 1) // time.Sleep(200 * time.Millisecond) t.Assert(array.Len(), 2) }) } func Test_Locker_TryLockFunc(t *testing.T) { //no expire gtest.C(t, func(t *gtest.T) { key := "testTryLockFunc" array := garray.New(true) go func() { gmlock.TryLockFunc(key, func() { array.Append(1) time.Sleep(200 * time.Millisecond) }) }() go func() { time.Sleep(100 * time.Millisecond) gmlock.TryLockFunc(key, func() { array.Append(1) }) }() go func() { time.Sleep(300 * time.Millisecond) gmlock.TryLockFunc(key, func() { array.Append(1) }) }() time.Sleep(150 * time.Millisecond) t.Assert(array.Len(), 1) time.Sleep(400 * time.Millisecond) t.Assert(array.Len(), 2) }) } func Test_Multiple_Goroutine(t *testing.T) { gtest.C(t, func(t *gtest.T) { ch := make(chan struct{}, 0) num := 1000 wait := sync.WaitGroup{} wait.Add(num) for i := 0; i < num; i++ { go func() { defer wait.Done() <-ch gmlock.Lock("test") defer gmlock.Unlock("test") time.Sleep(time.Millisecond) }() } close(ch) wait.Wait() }) gtest.C(t, func(t *gtest.T) { ch := make(chan struct{}, 0) num := 100 wait := sync.WaitGroup{} wait.Add(num * 2) for i := 0; i < num; i++ { go func() { defer wait.Done() <-ch gmlock.Lock("test") defer gmlock.Unlock("test") time.Sleep(time.Millisecond) }() } for i := 0; i < num; i++ { go func() { defer wait.Done() <-ch gmlock.RLock("test") defer gmlock.RUnlock("test") time.Sleep(time.Millisecond) }() } close(ch) wait.Wait() }) }