测试信号量实现时出错

问题描述 投票:0回答:1

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

semaphore.go

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)
    }

}


go concurrency mutex semaphore shared-memory
1个回答
0
投票

Wait中,当您唤醒并锁定时,无法保证条件仍然成立。锁定后,应再次检查条件:

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

Signal中,您应该在唤醒其他人之前count--

© www.soinside.com 2019 - 2024. All rights reserved.