浅谈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 包原子操作
66 0
|
7月前
|
存储 安全 Go
Golang深入浅出之-原子操作包(sync/atomic)在Go中的应用
【4月更文挑战第23天】Go语言的`sync/atomic`包支持原子操作,防止多线程环境中的数据竞争。包括原子整数和指针操作,以及原子标量函数。常见问题包括误用非原子操作、误解原子操作语义和忽略内存排序约束。解决方法是使用原子函数、结合其他同步原语和遵循内存约束。注意始终使用原子操作处理共享变量,理解其语义限制,并熟悉内存排序约束,以实现并发安全和高效的应用程序。
103 1
|
安全 Go
golang 系列:atomic 原子操作
当我们想要对某个变量并发安全的修改,除了使用官方提供的 mutex,还可以使用 sync/atomic 包的原子操作,它能够保证对变量的读取或修改期间不被其他的协程所影响。
577 0
golang 系列:atomic 原子操作
|
3月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
140 4
Golang语言之管道channel快速入门篇
|
3月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
71 4
Golang语言文件操作快速入门篇
|
3月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
117 3
Golang语言之gRPC程序设计示例
|
3月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
100 4
|
3月前
|
Go
Golang语言错误处理机制
这篇文章是关于Golang语言错误处理机制的教程,介绍了使用defer结合recover捕获错误、基于errors.New自定义错误以及使用panic抛出自定义错误的方法。
55 3
|
3月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
73 4
Golang语言goroutine协程篇
|
3月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
79 3
Golang语言之Prometheus的日志模块使用案例