Структура счетчик в конкурентной среде
Всем привет. Стоит задача разработать структуру счетчик который работает в конкурентной среде. Не уверен, что правильно понял термин "структура-счетчик". Может кто-то знает, что значит структура счетчик? Я понял так
package main
import (
"sync"
"github.com/udonetsm/help/helper"
)
type Counter struct {
num int
sync.RWMutex
}
func (c *Counter) Count(wg *sync.WaitGroup, finish, start int) int {
defer helper.PanicCapture("Count")
wg.Add(finish - start)
for c.num < finish {
go func() {
c.Lock()
c.num += 1
c.Unlock()
wg.Done()
}()
}
return c.num
}
func New(start int) *Counter {
defer helper.PanicCapture("INIT")
return &Counter{
num: start,
}
}
func Counting(start, finish int) {
defer helper.PanicCapture("Counting")
c := New(start)
wg := sync.WaitGroup{}
c.Count(&wg, finish, start)
wg.Wait()
}
Постоянно выдает панику
panic: sync: negative WaitGroup counter
package main
import (
"log"
"sync"
"time"
"github.com/udonetsm/help/helper"
)
type Counter struct {
num int
sync.RWMutex
}
func (c *Counter) Count(wg *sync.WaitGroup, finish, start int) int {
defer helper.PanicCapture("Count")
wg.Add(1)
go func() {
for i := start; i <= finish; i++ {
c.Lock()
c.num += 1
c.Unlock()
log.Println(c.num)
time.Sleep(time.Second)
}
wg.Done()
}()
wg.Wait()
return c.num
}
func New(start int) *Counter {
defer helper.PanicCapture("INIT")
return &Counter{
num: -1,
}
}
func Counting(start, finish int) {
defer helper.PanicCapture("Counting")
c := New(start)
wg := sync.WaitGroup{}
log.Println(c.Count(&wg, finish, start))
}
Так панику не кидает, не правильно Wait использовал. Но не знаю так ли я понял структура-счетчик
Ответы (1 шт):
Первое — вы корректно сделали структуру счетчика
Но вы очень усложнили работу с счетчиком — какие-то finsih и start ввели зачем-то. У него простой интерфейс:
Inc() для инкремента и Value() для получения текущего значения
Остальное просто конкурентная среда: что-то работает с тяжелой работой, что-то считает результат этой работы... главное чтобы результат был корректным, то есть горутины не читали конкуретно состояние и одновременно не увеличивали (ну напрмиер сразу парочка/тройка горутин не увеличили состояние счетчика 5 до 6)
package main
import (
"fmt"
"log"
"sync"
)
type Counter struct {
num int
sync.Mutex
}
func (c *Counter) Inc() {
c.Lock()
defer c.Unlock()
c.num += 1
}
func (c *Counter) Value() int {
return c.num
}
func main() {
cnt := &Counter{
num: 0,
}
finish := make(chan struct{})
go Do(cnt, finish)
select {
case <-finish:
log.Printf("Work done with count: %d", cnt.Value())
}
}
func Do(cnt *Counter, finish chan struct{}) {
wg := sync.WaitGroup{}
// Hard work in goroutine and finish work
for i := 0; i < 20; i++ {
wg.Add(1)
// Тяжелая работа
go func(num int, cnt *Counter, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", num)
cnt.Inc()
fmt.Printf("Worker %d done\n", num)
}(i, cnt, &wg)
}
wg.Wait()
finish <- struct{}{}
close(finish)
}