浅谈Golang原子atomic

简介: 浅谈Golang原子atomic

前言

  1. atomic 适用的场景 - 简单、简单、简单!不要将atomic用在复杂的业务逻辑中
  2. atomic.Value 与 mutex - 学习用两者解决问题的思路
  3. 了解 data race 机制 - atomic可以有效地减少数据竞争

代码

package main
import (
  "fmt"
  "sync"
  "sync/atomic"
)
func atomicAdd() {
  var data, data2 int64
  var wg sync.WaitGroup
  for i := 0; i < 1000; i++ {
    wg.Add(1)
    go func() {
      atomic.AddInt64(&data, 1)
      data2++
      wg.Done()
    }()
  }
  wg.Wait()
  fmt.Println("data", data, "data2", data2)
}
// From medium: https://medium.com/a-journey-with-go/go-how-to-reduce-lock-contention-with-the-atomic-package-ba3b2664b549
type Config struct {
  a []int
}
// 用 go run -race main.go atomic.go 观察data races
func dataRaces() {
  cfg := &Config{}
  go func() {
    i := 0
    for {
      i++
      cfg.a = []int{i, i + 1, i + 2, i + 3, i + 4, i + 5}
    }
  }()
  var wg sync.WaitGroup
  for n := 0; n < 4; n++ {
    wg.Add(1)
    go func() {
      for n := 0; n < 100; n++ {
        fmt.Printf("%v\n", cfg)
      }
      wg.Done()
    }()
  }
  wg.Wait()
}
func dataRacesWithLock() {
  var mu sync.RWMutex
  cfg := &Config{}
  go func() {
    i := 0
    for {
      i++
      mu.Lock()
      cfg.a = []int{i, i + 1, i + 2, i + 3, i + 4, i + 5}
      mu.Unlock()
    }
  }()
  var wg sync.WaitGroup
  for n := 0; n < 4; n++ {
    wg.Add(1)
    go func() {
      for n := 0; n < 100; n++ {
        mu.RLock()
        fmt.Printf("%v\n", cfg)
        mu.RUnlock()
      }
      wg.Done()
    }()
  }
  wg.Wait()
}
func dataRacesWithAtomic() {
  var v atomic.Value
  go func() {
    i := 0
    for {
      i++
      cfg := &Config{a: []int{i, i + 1, i + 2, i + 3, i + 4, i + 5}}
      v.Store(cfg)
    }
  }()
  var wg sync.WaitGroup
  for n := 0; n < 4; n++ {
    wg.Add(1)
    go func() {
      for n := 0; n < 100; n++ {
        cfg := v.Load()
        fmt.Printf("%v\n", cfg)
      }
      wg.Done()
    }()
  }
  wg.Wait()
}
// cas相关的代码,建议直接参考源码中的相关实现
目录
相关文章
|
存储 Go
Golang 语言标准库 sync/atomic 包原子操作
Golang 语言标准库 sync/atomic 包原子操作
197 0
|
存储 安全 Go
Golang深入浅出之-原子操作包(sync/atomic)在Go中的应用
【4月更文挑战第23天】Go语言的`sync/atomic`包支持原子操作,防止多线程环境中的数据竞争。包括原子整数和指针操作,以及原子标量函数。常见问题包括误用非原子操作、误解原子操作语义和忽略内存排序约束。解决方法是使用原子函数、结合其他同步原语和遵循内存约束。注意始终使用原子操作处理共享变量,理解其语义限制,并熟悉内存排序约束,以实现并发安全和高效的应用程序。
264 1
|
安全 Go
golang 系列:atomic 原子操作
当我们想要对某个变量并发安全的修改,除了使用官方提供的 mutex,还可以使用 sync/atomic 包的原子操作,它能够保证对变量的读取或修改期间不被其他的协程所影响。
744 0
golang 系列:atomic 原子操作
|
4月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
293 3
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
722 4
Golang语言之管道channel快速入门篇
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
316 4
Golang语言文件操作快速入门篇
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
614 3
Golang语言之gRPC程序设计示例
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
410 4
|
Go
Golang语言错误处理机制
这篇文章是关于Golang语言错误处理机制的教程,介绍了使用defer结合recover捕获错误、基于errors.New自定义错误以及使用panic抛出自定义错误的方法。
199 3
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
313 4
Golang语言之Prometheus的日志模块使用案例

推荐镜像

更多