1. 简介
实现与pythonthreading.Barrier
库类似的功能,多线程同时等待达到指定数量一起放行。
有待改进地方:
wait
方法没有支持context
控制。
2. 代码
import (
"context"
"golang.org/x/sync/semaphore"
"sync/atomic"
)
type Barrier struct {
count int64 // 记录当前多少
amount int64 // 记录多少放行
entry *semaphore.Weighted
exit *semaphore.Weighted
}
func NewBarrier(n int64) *Barrier {
b := &Barrier{
count: 0,
amount: n,
entry: semaphore.NewWeighted(n),
exit: semaphore.NewWeighted(n),
}
_ = b.exit.Acquire(context.Background(), n)
return b
}
func (b *Barrier) Wait() {
ctx := context.Background()
// 限制进入数量
_ = b.entry.Acquire(context.Background(), 1)
// 如果是最后一个人,放行前面所有包括自己。
if atomic.AddInt64(&b.count, 1) == b.amount {
defer func() {
b.count = 0
b.entry.Release(b.amount)
}()
// 放行所有
b.exit.Release(b.amount)
}
// 等待放行
_ = b.exit.Acquire(ctx, 1)
}
测试
func TestBarrier(t *testing.T) {
b := NewBarrier(2)
for i := 1; i <= 10; i++ {
go func(id int) {
b.Wait()
t.Log("waited", id)
}(i)
time.Sleep(time.Second)
}
}