我正在创建全局计数器,可以在goroutines之间共享.参考这个问题,以下代码可能满足我的需求.
但是,如果存在大量并发请求,是否会将相同的数字分配给两个以上的goroutines?如果是这样我怎么能避免这种情况?
谢谢!
补充评论)这个问题与我粘贴的链接不同,因为我想知道的是如何使用频道计数器避免重复.如果唯一可能的解决方案是sync.Mutex或atomic等其他实现,我将使用它.然而,根据链接(再次),频道似乎是最好的选择.任何评论或答案都非常有用.提前致谢.我是多线程编码的新手,也可能是愚蠢的问题.对不起
package main
import (
"fmt"
"time"
)
var counter int
var counter_chan chan int
func main() {
counter_chan = make(chan int, 100)
counter = 0
go func() {
for {
select {
case chanc := <-counter_chan:
counter += chanc
fmt.Printf("%d \n", counter)
}
}
}()
for i := 0; i < 10; i++ {
go AddCounter(counter_chan)
}
time.Sleep(time.Second)
fmt.Printf("Total Count is ... %d \n", GetCount())
}
func AddCounter(ch chan int) {
ch <- 1
}
func GetCount() int {
return counter
}
func ResetCount() {
if counter > 8190 {
counter = 0
}
}
Run Code Online (Sandbox Code Playgroud)
- 编辑2018年5月14日
假设以下代码对于获取和重置值是线程安全的.我对吗?
package main
import (
"fmt"
"time"
)
var counter int
var addCounterChan chan int
var readCounterChan chan int
func main() {
addCounterChan = make(chan int, 100)
readCounterChan = make(chan int, 100)
counter = 0
go func() {
for {
select {
case val := <-addCounterChan:
counter += val
if counter > 5 {
counter = 0
}
readCounterChan <- counter
fmt.Printf("%d \n", counter)
}
}
}()
for i := 0; i < 10; i++ {
go AddCounter(addCounterChan)
}
time.Sleep(time.Second)
for i := 0; i < 10; i++ {
fmt.Printf("Total Count #%d is ... %d \n", (i + 1), GetCount(readCounterChan))
}
}
// Following two functions will be implemented in another package in real case.
func AddCounter(ch chan int) {
ch <- 1
}
func GetCount(ch chan int) int {
r := <-ch
return r
}
Run Code Online (Sandbox Code Playgroud)
您问题的直接答案是:您粘贴的代码会安全地更新计数器,但不会安全地读取或重置它.
但是,与您链接的问题中的接受答案相反,实现共享计数器的最简单,最有效的方法是使用原子包.它可以用于原子地递增几种常见类型.例:
var globalCounter *int32 = new(int32)
// .. later in your code
currentCount := atomic.AddInt32(globalCounter, 1)
Run Code Online (Sandbox Code Playgroud)
如问题所示,使用sync.Mutex创建一个具有添加、获取和重置操作的计数器。
type counter struct {
mu sync.Mutex
n int
}
func (c *counter) Add() {
c.mu.Lock()
c.n++
c.mu.Unlock()
}
func (c *counter) Get() int {
c.mu.Lock()
n := c.n
c.mu.Unlock()
return n
}
func (c *counter) Reset() {
c.mu.Lock()
if c.n > 8190 {
c.n = 0
}
c.mu.Unlock()
}
Run Code Online (Sandbox Code Playgroud)
如果不需要重置功能,则使用sync/atomic。
type counter struct {
n int32
}
func (c *counter) Add() {
atomic.AddInt32(&c.n, 1)
}
func (c *counter) Get() int {
return int(atomic.LoadInt32(&c.n))
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1336 次 |
| 最近记录: |