当前位置: 首页 > article >正文

Golang笔记|Atomic

作用与优势

atomic 包是 Go 语言中用于进行原子操作的标准库。原子操作是一种在多线程并发编程中用来确保数据安全的机制,它可以防止多个线程同时访问同一个资源而导致的数据竞争问题。

atomic 包中的函数是原子操作,它们在执行时不会被中断,从而确保操作的不可分割性。这对于执行复杂的操作,如比较并交换,是非常重要的。

在某些情况下,使用互斥锁来保护共享变量可能会导致额外的锁开销和上下文切换,从而影响性能。atomic 包的原子操作不需要使用锁,可以减少这些开销。

原子操作通常比互斥锁更高效,特别是在一些轻量级的操作中。在高并发的情况下,使用原子操作可以提高程序的性能。

适用场景

  • 计数器和累加器: 当多个协程需要对一个共享的计数器或累加器进行增加、减少或重置操作时,使用 atomic包可以避免数据竞争,确保操作的原子性。
  • 标志位和状态切换: 当多个协程需要读取和修改某个共享的标志位或状态值时,使用 atomic包可以确保状态的正确性,避免并发修改导致的问题。
  • 缓存更新和缓存失效: 在缓存中存储的数据需要经常更新,且更新频率较高时,使用 atomic包可以保证更新操作的一致性,防止多个协程同时更新而导致的问题。
  • 资源池管理: 当多个协程需要从资源池中获取或释放资源时,使用 atomic 包可以保证资源池的状态正确,避免资源泄漏和竞争条件。
  • 引用计数: 在一些场景中,可能需要使用引用计数来管理共享资源的生命周期。使用 atomic 包可以确保引用计数的增加和减少操作是原子的。

atomic包中的函数

  1. atomic.AddInt32, atomic.AddInt64,atomic.AddUint32,atomic.AddUint64:原子地将指定的值加到一个整数变量上。
  2. atomic.LoadInt32,atomic.LoadInt64,atomic.LoadUint32,atomic.LoadUint64:原子地读取一个整数变量的值。
package main

import (
   "fmt"
   "sync"
   "sync/atomic"
   "time"
)

func main() {
   var counter int64
   var wg sync.WaitGroup

   for i := 0; i < 10; i++ {
      wg.Add(1)
      go func() {
         for j := 0; j < 1000; j++ {
            atomic.AddInt64(&counter, 1)
         }
         wg.Done()
      }()
   }

   wg.Wait()
   fmt.Println("Counter value:", atomic.LoadInt64(&counter))
}

  1. atomic.StoreInt32, atomic.StoreInt64, atomic.StoreUint32, atomic.StoreUint64:原子地将指定的值写入到一个整数变量中。
package main

import (
   "fmt"
   "sync"
   "sync/atomic"
)

func main() {
   var value int64
   var wg sync.WaitGroup

   // 启动多个协程尝试存储值
   for i := 0; i < 10; i++ {
      wg.Add(1)
      go func(i int) {
         defer wg.Done()

         // 原子地将值设置为协程的编号
         atomic.StoreInt64(&value, int64(i))
         fmt.Printf("Goroutine %d: Stored value %d\n", i, i)
      }(i)
   }

   wg.Wait()
   fmt.Printf("Final value: %d\n", value)
}


  1. atomic.CompareAndSwapInt32, atomic.CompareAndSwapInt64, atomic.CompareAndSwapUint32, atomic.CompareAndSwapUint64:比较并交换,比较当前addr地址里的值是不是old,如果不等于old,就返回false; 如果当前等于old,就把此地址的值替换成new值,返回true。
package main

import (
   "fmt"
   "sync"
   "sync/atomic"
)

func main() {
   var value int64 = 0
   var wg sync.WaitGroup

   // 启动多个协程尝试修改值
   for i := 0; i < 10; i++ {
      wg.Add(1)
      go func(i int) {
         defer wg.Done()

         // 尝试将值从旧值0修改为新值10
         swapped := atomic.CompareAndSwapInt64(&value, 0, 10)
         if swapped {
            fmt.Printf("Goroutine %d: Value swapped successfully\n", i)
         } else {
            fmt.Printf("Goroutine %d: Value was not swapped\n", i)
         }
      }(i)
   }

   wg.Wait()
   fmt.Printf("Final value: %d\n", value)
}


  1. atomic.SwapInt32, atomic.SwapInt64, atomic.SwapUint32, atomic.SwapUint64:原子地交换一个整数变量的值。如果不需要比较旧值,只是比较粗暴地替换的话,就可以使用Swap方法。

```go
package main

import (
   "fmt"
   "sync"
   "sync/atomic"
)

func main() {
   var value int64 = 5
   var wg sync.WaitGroup

   // 启动多个协程尝试交换值
   for i := 0; i < 10; i++ {
      wg.Add(1)
      go func(i int) {
         defer wg.Done()

         // 原子地交换值为新值10,并获取旧值
         oldValue := atomic.SwapInt64(&value, 10)
         fmt.Printf("Goroutine %d: Swapped value from %d to 10\n", i, oldValue)
      }(i)
   }

   wg.Wait()
   fmt.Printf("Final value: %d\n", value)
}



http://www.kler.cn/a/154198.html

相关文章:

  • 基于Python空气质量可视化及预测
  • PHP代码审计 --MVC模型开发框架rce示例
  • CPU执行指令的过程
  • 【网络安全】网络安全防护体系
  • ThinkPHP 模型如何更新数据
  • 微服务瞎写
  • 【一周安全资讯1202】信安标委发布《网络安全标准实践指南—网络安全产品互联互通 告警信息格式》;网络安全纳入注册会计师考试科目
  • Android 手机屏幕适配方式和原理
  • (一)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • 【UGUI】Unity为下拉菜单添加选项(DropDown)
  • SQL Server对象类型(7)——4.7.触发器(Trigger)
  • 自定义类型-结构体,联合体和枚举-C语言
  • matlab 无迹卡尔曼滤波
  • 力扣129. 求根节点到叶节点数字之和
  • Git自动化利器:使用Node.js脚本定制化提交消息处理
  • 电大搜题微信公众号详解,助力学习者轻松考试
  • web:very_easy_sql(sql、ssrf、gopher协议sql注入)
  • zookeeper集群+kaafka集群
  • 二叉树遍历及应用
  • 大厂面试整理
  • Linux操作系统 2.Linux基础命令
  • Python字典类型
  • MyBatis的创建,简单易懂的一篇blog
  • LeetCode [中等]98. 验证二叉搜索树
  • uniapp-从后台返回的一串地址信息上,提取省市区进行赋值
  • 数据结构--堆排序