MST

星途 面试题库

面试题:Go并发数据竞争场景下的原子操作应用

假设在一个高并发的Go程序中,多个goroutine需要对一个共享的整数变量进行增减操作,要求避免数据竞争。请详细说明如何使用原子操作(如`atomic`包)来实现,并阐述原子操作在这种场景下相较于互斥锁的优缺点。
17.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

使用原子操作实现共享整数变量增减

在Go语言中,可以使用atomic包来实现对共享整数变量的原子操作,避免数据竞争。以下是一个示例代码:

package main

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

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

    // 模拟10个goroutine进行增减操作
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            // 增加操作
            atomic.AddInt64(&sharedVar, 1)
            // 减少操作
            atomic.AddInt64(&sharedVar, -1)
        }()
    }

    wg.Wait()
    fmt.Println("Final value of sharedVar:", sharedVar)
}

在上述代码中,使用atomic.AddInt64函数对sharedVar进行原子性的增减操作。atomic.AddInt64函数接收两个参数,第一个是指向共享变量的指针,第二个是要增加或减少的值(负数表示减少)。

原子操作相较于互斥锁的优缺点

优点

  1. 性能更高:原子操作通常在硬件层面直接支持,不需要像互斥锁那样进行上下文切换和调度,因此在高并发场景下,原子操作的性能更高,尤其是对于简单的读 - 修改 - 写操作。
  2. 轻量级:原子操作不需要额外的锁对象,占用的资源更少,实现更简单直接,适用于对性能要求极高且操作简单的场景。

缺点

  1. 功能有限:原子操作只能对简单的数据类型(如整数、指针等)进行操作,并且只支持有限的几种操作(如加法、比较并交换等)。对于复杂的数据结构或复杂的操作逻辑,原子操作无法满足需求,此时需要使用互斥锁。
  2. 调试困难:由于原子操作在底层硬件层面执行,调试时难以追踪和理解其执行过程,出现问题时定位问题的难度较大。而互斥锁在代码层面相对更容易理解和调试。