clicker

This function can be very helpful for defining thread-safe components really easily. A very obvious example could be a simple integer counter that uses Add to change the counter, Load to retrieve the current value, and Store to reset it:

type clicker int32

func (c *clicker) Click() int32 {
return atomic.AddInt32((*int32)(c), 1)
}

func (c *clicker) Reset() {
atomic.StoreInt32((*int32)(c), 0)
}

func (c *clicker) Value() int32 {
return atomic.LoadInt32((*int32)(c))
}

We can see it in action in a simple program, which tries to read, write, and reset the counter concurrently. 

We define the clicker and WaitGroup and add the correct number of elements to the wait group as follows:

c := clicker(0)
wg := sync.WaitGroup{}
// 2*iteration + reset at 5
wg.Add(21)

We can launch a bunch of goroutines doing different actions, such as: 10 reads, 10 adds, and a reset:

for i := 0; i < 10; i++ {
go func() {
c.Click()
fmt.Println("click")
wg.Done()
}()
go func() {
fmt.Println("load", c.Value())
wg.Done()
}()
if i == 0 || i%5 != 0 {
continue
}
go func() {
c.Reset()
fmt.Println("reset")
wg.Done()
}()
}
wg.Wait()

We will see the clicker acting as it is supposed to, executing concurrent sums without race conditions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.20.224.107