diff --git a/collection/zset/skiplist.go b/collection/zset/skiplist.go index 07161fbf..e5e44283 100644 --- a/collection/zset/skiplist.go +++ b/collection/zset/skiplist.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/collection/zset/zset.go b/collection/zset/zset.go index 46f46336..72801bab 100644 --- a/collection/zset/zset.go +++ b/collection/zset/zset.go @@ -382,8 +382,8 @@ func (z *Float64Set) RevRangeByScoreWithOpt(max, min float64, opt RangeOpt) []Fl // // RemoveRangeByRank is the replacement of ZREMRANGEBYRANK command of redis. func (z *Float64Set) RemoveRangeByRank(start, stop int) []Float64Node { - z.mu.RLock() - defer z.mu.RUnlock() + z.mu.Lock() + defer z.mu.Unlock() // Convert negative rank to positive. if start < 0 { diff --git a/collection/zset/zset_test.go b/collection/zset/zset_test.go index 87056fcd..c404590b 100644 --- a/collection/zset/zset_test.go +++ b/collection/zset/zset_test.go @@ -18,6 +18,8 @@ import ( "fmt" "math/rand" "sort" + "strconv" + "sync" "testing" "time" @@ -493,6 +495,26 @@ func TestFloat64SetRemoveRangeByRank(t *testing.T) { assert.Equal(t, N, z.Len()+len(actualNs)) } +func TestFloat64SetRemoveRangeByRankConcurrently(t *testing.T) { + const N = 10000 + z := NewFloat64() + for i := 0; i < N; i++ { + z.Add(float64(i), strconv.Itoa(i)) + } + const G = 10 + wg := sync.WaitGroup{} + for i := 0; i < G; i++ { + wg.Add(1) + go func() { + defer wg.Done() + start := fastrand.Intn(N / 2) + stop := N/2 + start + z.RemoveRangeByRank(start, stop) + }() + } + wg.Wait() +} + func TestFloat64SetRemoveRangeByScore(t *testing.T) { const N = 1000 z := NewFloat64()