瀏覽代碼

ring struct add lock (#434)

Co-authored-by: liuhuan210 <liuhuan210@jd.com>
理工男 4 年之前
父節點
當前提交
7b3c3de35e
共有 2 個文件被更改,包括 36 次插入0 次删除
  1. 8 0
      core/collection/ring.go
  2. 28 0
      core/collection/ring_test.go

+ 8 - 0
core/collection/ring.go

@@ -1,8 +1,11 @@
 package collection
 
+import "sync"
+
 type Ring struct {
 	elements []interface{}
 	index    int
+	lock     sync.Mutex
 }
 
 func NewRing(n int) *Ring {
@@ -16,11 +19,16 @@ func NewRing(n int) *Ring {
 }
 
 func (r *Ring) Add(v interface{}) {
+	r.lock.Lock()
+	defer r.lock.Unlock()
 	r.elements[r.index%len(r.elements)] = v
 	r.index++
 }
 
 func (r *Ring) Take() []interface{} {
+	r.lock.Lock()
+	defer r.lock.Unlock()
+
 	var size int
 	var start int
 	if r.index > len(r.elements) {

+ 28 - 0
core/collection/ring_test.go

@@ -1,6 +1,7 @@
 package collection
 
 import (
+	"sync"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -29,3 +30,30 @@ func TestRingMore(t *testing.T) {
 	elements := ring.Take()
 	assert.ElementsMatch(t, []interface{}{6, 7, 8, 9, 10}, elements)
 }
+
+func BenchmarkRingAdd(b *testing.B) {
+	ring := NewRing(500)
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			for i := 0; i < b.N; i++ {
+				ring.Add(i)
+			}
+		}
+	})
+}
+
+func TestRingAdd(t *testing.T) {
+	ring := NewRing(5051)
+	wg := sync.WaitGroup{}
+	for i := 1; i <= 100; i++ {
+		wg.Add(1)
+		go func(i int) {
+			defer wg.Done()
+			for j := 1; j <= i; j++ {
+				ring.Add(i)
+			}
+		}(i)
+	}
+	wg.Wait()
+	assert.Equal(t, 5050, len(ring.Take()))
+}