go原子级内存操作实现

 更新时间:2024年02月11日 09:34:20   作者:别人家的孩子zyh  
原子级内存操作是在多线程并发执行时,能够确保某个内存操作是不可中断的操作,本文主要介绍了go原子级内存操作实现,具有一定的参考价值,感兴趣的可以了解一下

原子级内存操作是在多线程并发执行时,能够确保某个内存操作是不可中断的操作。在计算机系统中,CPU执行指令是基本的原子操作,即一个指令的执行是不可被中断的。然而,在多线程并发的环境中,一个线程执行的指令可能被其他线程的操作所干扰,导致数据不一致或产生竞态条件。

原子操作保证了对共享数据的操作是不可分割的,即要么完全执行,要么完全不执行。在多线程环境中,原子操作通常用于解决并发访问共享资源时可能出现的竞态条件问题。

在编程中,原子操作通常使用特殊的CPU指令或者操作系统提供的原子操作函数来实现。在Go语言中,sync/atomic 包提供了一组原子操作的函数,例如 Add, CompareAndSwap, Load, Store 等,用于执行原子级别的内存操作。

以下是一个使用Go中的sync/atomic包实现的简单示例:

package main

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

func main() {
	var counter int64

	// 使用原子操作增加计数器的值
	atomic.AddInt64(&counter, 1)

	// 使用原子操作获取计数器的值
	value := atomic.LoadInt64(&counter)
	fmt.Println("Counter:", value)

	// 使用原子操作比较并交换计数器的值
	success := atomic.CompareAndSwapInt64(&counter, 1, 2)
	fmt.Println("Swap success:", success)

	// 在多线程环境中,原子操作确保对共享数据的操作是线程安全的
	go func() {
		atomic.AddInt64(&counter, 1)
	}()

	go func() {
		atomic.AddInt64(&counter, 1)
	}()

	time.Sleep(time.Millisecond) // 等待goroutine执行完毕

	// 最终的计数器值
	finalValue := atomic.LoadInt64(&counter)
	fmt.Println("Final Counter:", finalValue)
}

运行结果

Counter: 1
Swap success: true
Final Counter: 4

原子操作与互斥锁的区别

互斥锁是一种数据结构,使你可以执行一系列互斥操作。而原子操作是互斥的单个操作,这意味着没有其他线程可以打断它。那么就Go语言里atomic包里的原子操作和sync包提供的同步锁有什么不同呢?

首先atomic操作的优势是更轻量,比如CAS可以在不形成临界区和创建互斥量的情况下完成并发安全的值替换操作。这可以大大的减少同步对程序性能的损耗。

原子操作也有劣势。还是以CAS操作为例,使用CAS操作的做法趋于乐观,总是假设被操作值未曾被改变(即与旧值相等),并一旦确认这个假设的真实性就立即进行值替换,那么在被操作值被频繁变更的情况下,CAS操作并不那么容易成功。而使用互斥锁的做法则趋于悲观,我们总假设会有并发的操作要修改被操作的值,并使用锁将相关操作放入临界区中加以保护。

所以总结下来原子操作与互斥锁的区别有:

  • 互斥锁是一种数据结构,用来让一个线程执行程序的关键部分,完成互斥的多个操作。
  • 原子操作是针对某个值的单个互斥操作。
  • 可以把互斥锁理解为悲观锁,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。

atomic包提供了底层的原子性内存原语,这对于同步算法的实现很有用。这些函数一定要非常小心地使用,使用不当反而会增加系统资源的开销,对于应用层来说,最好使用通道或sync包中提供的功能来完成同步操作。

针对atomic包的观点在Google的邮件组里也有很多讨论,其中一个结论解释是:

应避免使用该包装。或者,阅读C ++ 11标准的“原子操作”一章;如果您了解如何在C ++中安全地使用这些操作,那么你才能有安全地使用Go的sync/atomic包的能力。

到此这篇关于go原子级内存操作实现的文章就介绍到这了,更多相关go原子级内存操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang如何修改json文件内容的方法示例

    golang如何修改json文件内容的方法示例

    这篇文章主要介绍了golang如何修改json文件内容的方法示例,使用一个例子说明golang如何访问和修改json文件,有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • 使用go实现删除sql里面的注释和字符串功能(demo)

    使用go实现删除sql里面的注释和字符串功能(demo)

    这篇文章主要介绍了使用go实现删除sql里面的注释和字符串功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Go 文件读取和写入操作全面讲解

    Go 文件读取和写入操作全面讲解

    这篇文章主要为大家介绍了Go文件的读取和写入操作示例的全面详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • 利用Golang如何调用Linux命令详解

    利用Golang如何调用Linux命令详解

    这篇文章主要给大家介绍了Golang中使用os/exec来执行 Linux 命令的相关资料,文中给出了详细的示例代码,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-05-05
  • golang开发go包依赖管理godep使用教程

    golang开发go包依赖管理godep使用教程

    这篇文章主要为大家介绍了golang开发go包依赖管理godep使用教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • 详解如何在golang镜像中设置指定时区

    详解如何在golang镜像中设置指定时区

    这篇文章主要为大家详细介绍了如何在golang镜像中设置指定时区,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以了解一下
    2023-04-04
  • Golang AGScheduler动态持久化任务调度的强大库使用实例

    Golang AGScheduler动态持久化任务调度的强大库使用实例

    这篇文章主要为大家介绍了Golang AGScheduler动态持久化任务调度的强大库使用实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • GO开发编辑器安装图文详解

    GO开发编辑器安装图文详解

    这篇文章主要介绍了GO开发编辑器安装,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • golang 实现时间戳和时间的转化

    golang 实现时间戳和时间的转化

    这篇文章主要介绍了golang 实现时间戳和时间的转化操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • Go语言使用net/http实现简单登录验证和文件上传功能

    Go语言使用net/http实现简单登录验证和文件上传功能

    这篇文章主要介绍了Go语言使用net/http实现简单登录验证和文件上传功能,使用net/http模块编写了一个简单的登录验证和文件上传的功能,在此做个简单记录,需要的朋友可以参考下
    2023-07-07

最新评论