测试信号量实现时出错

我正在练习并发编程,并且已经着手实现了几种模式和结构。我还添加了一些测试,在这些测试中,我将信号量用作互斥体以增加共享计数器。我的实现显然存在问题,因为在几次运行测试文件后,有些测试通过了,而另一些则失败了。 我的猜测是,多个线程在不阻塞的情况下通过了Wait()调用,并且可以并发访问计数器变量,但是我不知道为什么。任何帮助表示赞赏!

信号量

package semaphore

import (
    "sync"
)

type Semaphore struct {
    capacity int

    count int
    sync.Mutex
    condition chan bool
}

func (s *Semaphore) Wait() {
    s.Lock()
    defer s.Unlock()

    if s.count == s.capacity {
        s.Unlock()
        <-s.condition
        s.Lock()
    }

    s.count++

}

func (s *Semaphore) Signal() {
    s.Lock()
    defer s.Unlock()

    select {
    case s.condition <- true:
    default:
    }

    s.count--

}

func NewSemaphore(n int) *Semaphore {
    return &Semaphore{count: 0, capacity: n, condition: make(chan bool)}
}

semaphore_test.go

package semaphore

import (
    "sync"
    "testing"
)

func TestMutexSemaphore(t *testing.T) {

    s := NewSemaphore(1)
    wg := sync.WaitGroup{}
    sharedCounter := 0
    iters := 25
    n := 20

    testfun := func(mutex *Semaphore) {
        defer wg.Done()
        for j := 0; j < iters; j++ {
            s.Wait()
            sharedCounter++
            s.Signal()
        }

    }
    wg.Add(n)
    for i := 0; i < n; i++ {
        go testfun(s)
    }

    wg.Wait()
    if sharedCounter != iters*n {
        t.Errorf("Bad counter value:%d expected %d", sharedCounter, n*iters)
    }

}


评论
  • 翠寒凝
    翠寒凝 回复

    In Wait, when you wake up and lock, there is no guarantee that the condition still holds. After locking, you should check the condition again:

       for s.count == s.capacity {
            s.Unlock()
            <-s.condition
            s.Lock()
        }
    

    In Signal you should count-- before waking up others.